diff options
Diffstat (limited to 'src/aig/ntl')
-rw-r--r-- | src/aig/ntl/module.make | 11 | ||||
-rw-r--r-- | src/aig/ntl/ntl.h | 277 | ||||
-rw-r--r-- | src/aig/ntl/ntlAig.c | 596 | ||||
-rw-r--r-- | src/aig/ntl/ntlCheck.c | 126 | ||||
-rw-r--r-- | src/aig/ntl/ntlDfs.c | 184 | ||||
-rw-r--r-- | src/aig/ntl/ntlMan.c | 196 | ||||
-rw-r--r-- | src/aig/ntl/ntlMap.c | 624 | ||||
-rw-r--r-- | src/aig/ntl/ntlObj.c | 238 | ||||
-rw-r--r-- | src/aig/ntl/ntlReadBlif.c | 1163 | ||||
-rw-r--r-- | src/aig/ntl/ntlTable.c | 217 | ||||
-rw-r--r-- | src/aig/ntl/ntlTime.c | 128 | ||||
-rw-r--r-- | src/aig/ntl/ntlWriteBlif.c | 127 | ||||
-rw-r--r-- | src/aig/ntl/ntl_.c | 47 |
13 files changed, 3934 insertions, 0 deletions
diff --git a/src/aig/ntl/module.make b/src/aig/ntl/module.make new file mode 100644 index 00000000..f47108a4 --- /dev/null +++ b/src/aig/ntl/module.make @@ -0,0 +1,11 @@ +SRC += src/aig/ntl/ntlAig.c \ + src/aig/ntl/ntlCheck.c \ + src/aig/ntl/ntlDfs.c \ + src/aig/ntl/ntlMan.c \ + src/aig/ntl/ntlMap.c \ + src/aig/ntl/ntlObj.c \ + src/aig/ntl/ntlReadBlif.c \ + src/aig/ntl/ntlTable.c \ + src/aig/ntl/ntlTime.c \ + src/aig/ntl/ntlWriteBlif.c + diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h new file mode 100644 index 00000000..dbd8676b --- /dev/null +++ b/src/aig/ntl/ntl.h @@ -0,0 +1,277 @@ +/**CFile**************************************************************** + + FileName [ntl.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __NTL_H__ +#define __NTL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig.h" +#include "tim.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ntl_Man_t_ Ntl_Man_t; +typedef struct Ntl_Mod_t_ Ntl_Mod_t; +typedef struct Ntl_Obj_t_ Ntl_Obj_t; +typedef struct Ntl_Net_t_ Ntl_Net_t; +typedef struct Ntl_Lut_t_ Ntl_Lut_t; + +// object types +typedef enum { + NTL_OBJ_NONE, // 0: non-existent object + NTL_OBJ_PI, // 1: primary input + NTL_OBJ_PO, // 2: primary output + NTL_OBJ_LATCH, // 3: latch node + NTL_OBJ_NODE, // 4: logic node + NTL_OBJ_BOX, // 5: white box or black box + NTL_OBJ_VOID // 6: unused object +} Ntl_Type_t; + +struct Ntl_Man_t_ +{ + // models of this design + char * pName; // the name of this design + char * pSpec; // the name of input file + Vec_Ptr_t * vModels; // the array of all models used to represent boxes + // memory managers + Aig_MmFlex_t * pMemObjs; // memory for objects + Aig_MmFlex_t * pMemSops; // memory for SOPs + // extracted representation + Vec_Ptr_t * vCis; // the primary inputs of the extracted part + Vec_Ptr_t * vCos; // the primary outputs of the extracted part + Vec_Ptr_t * vNodes; // the nodes of the abstracted part + Vec_Int_t * vBox1Cos; // the first COs of the boxes + Aig_Man_t * pAig; // the extracted AIG + Tim_Man_t * pManTime; // the timing manager +}; + +struct Ntl_Mod_t_ +{ + // model description + Ntl_Man_t * pMan; // the model manager + char * pName; // the model name + Vec_Ptr_t * vObjs; // the array of all objects + Vec_Ptr_t * vPis; // the array of PI objects + Vec_Ptr_t * vPos; // the array of PO objects + int nObjs[NTL_OBJ_VOID]; // counter of objects of each type + // hashing names into nets + Ntl_Net_t ** pTable; // the hash table of names into nets + int nTableSize; // the allocated table size + int nEntries; // the number of entries in the hash table + // delay information + Vec_Int_t * vDelays; + Vec_Int_t * vArrivals; + Vec_Int_t * vRequireds; + float * pDelayTable; +}; + +struct Ntl_Obj_t_ +{ + Ntl_Mod_t * pModel; // the model + unsigned Type : 3; // object type + unsigned Id : 27; // object ID + unsigned MarkA : 1; // temporary mark + unsigned MarkB : 1; // temporary mark + short nFanins; // the number of fanins + short nFanouts; // the number of fanouts + union { // functionality + Ntl_Mod_t * pImplem; // model (for boxes) + char * pSop; // SOP (for logic nodes) + unsigned LatchId; // init state + register class (for latches) + }; + Ntl_Net_t * pFanio[0]; // fanins/fanouts +}; + +struct Ntl_Net_t_ +{ + Ntl_Obj_t * pDriver; // driver of the net + Ntl_Net_t * pNext; // next net in the hash table + Aig_Obj_t * pFunc; // the AIG representation + char nVisits; // the number of times the net is visited + char fMark; // temporary mark + char pName[0]; // the name of this net +}; + +struct Ntl_Lut_t_ +{ + int Id; // the ID of the root AIG node + int nFanins; // the number of fanins + int * pFanins; // the array of fanins + unsigned * pTruth; // the truth table +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// INLINED FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ntl_ModelPiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI]; } +static inline int Ntl_ModelPoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO]; } +static inline int Ntl_ModelNodeNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_NODE]; } +static inline int Ntl_ModelLatchNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_LATCH]; } +static inline int Ntl_ModelBoxNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_BOX]; } +static inline int Ntl_ModelCiNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PI] + p->nObjs[NTL_OBJ_LATCH]; } +static inline int Ntl_ModelCoNum( Ntl_Mod_t * p ) { return p->nObjs[NTL_OBJ_PO] + p->nObjs[NTL_OBJ_LATCH]; } + +static inline Ntl_Obj_t * Ntl_ModelPi( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPis, i); } +static inline Ntl_Obj_t * Ntl_ModelPo( Ntl_Mod_t * p, int i ) { return Vec_PtrEntry(p->vPos, i); } + +static inline char * Ntl_ModelPiName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPi(p, i)->pFanio[0]->pName; } +static inline char * Ntl_ModelPoName( Ntl_Mod_t * p, int i ) { return Ntl_ModelPo(p, i)->pFanio[0]->pName; } + +static inline int Ntl_ModelIsBlackBox( Ntl_Mod_t * p ) { return Ntl_ModelPiNum(p) + Ntl_ModelPoNum(p) == Vec_PtrSize(p->vObjs); } + +static inline int Ntl_ObjFaninNum( Ntl_Obj_t * p ) { return p->nFanins; } +static inline int Ntl_ObjFanoutNum( Ntl_Obj_t * p ) { return p->nFanouts; } + +static inline int Ntl_ObjIsPi( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PI; } +static inline int Ntl_ObjIsPo( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_PO; } +static inline int Ntl_ObjIsNode( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_NODE; } +static inline int Ntl_ObjIsLatch( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_LATCH; } +static inline int Ntl_ObjIsBox( Ntl_Obj_t * p ) { return p->Type == NTL_OBJ_BOX; } + +static inline Ntl_Net_t * Ntl_ObjFanin0( Ntl_Obj_t * p ) { return p->pFanio[0]; } +static inline Ntl_Net_t * Ntl_ObjFanout0( Ntl_Obj_t * p ) { return p->pFanio[p->nFanins]; } + +static inline Ntl_Net_t * Ntl_ObjFanin( Ntl_Obj_t * p, int i ) { return p->pFanio[i]; } +static inline Ntl_Net_t * Ntl_ObjFanout( Ntl_Obj_t * p, int i ) { return p->pFanio[p->nFanins+1]; } + +static inline void Ntl_ObjSetFanin( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[i] = pNet; } +static inline void Ntl_ObjSetFanout( Ntl_Obj_t * p, Ntl_Net_t * pNet, int i ) { p->pFanio[p->nFanins+i] = pNet; pNet->pDriver = p; } + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Ntl_ManForEachModel( p, pNtl, i ) \ + Vec_PtrForEachEntry( p->vModels, pNtl, i ) +#define Ntl_ManForEachCiNet( p, pNtl, i ) \ + Vec_PtrForEachEntry( p->vCis, pNtl, i ) +#define Ntl_ManForEachCoNet( p, pNtl, i ) \ + Vec_PtrForEachEntry( p->vCos, pNtl, i ) +#define Ntl_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \ + if ( !Ntl_ObjIsNode(pObj) ) {} else +#define Ntl_ManForEachBox( p, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(p->vNodes)) && (((pObj) = Vec_PtrEntry(p->vNodes, i)), 1); i++ ) \ + if ( !Ntl_ObjIsBox(pObj) ) {} else + +#define Ntl_ModelForEachPi( pNtl, pObj, i ) \ + Vec_PtrForEachEntry( pNtl->vPis, pObj, i ) +#define Ntl_ModelForEachPo( pNtl, pObj, i ) \ + Vec_PtrForEachEntry( pNtl->vPos, pObj, i ) +#define Ntl_ModelForEachObj( pNtl, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ + if ( pObj == NULL ) {} else +#define Ntl_ModelForEachLatch( pNtl, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ + if ( !Ntl_ObjIsLatch(pObj) ) {} else +#define Ntl_ModelForEachNode( pNtl, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ + if ( !Ntl_ObjIsNode(pObj) ) {} else +#define Ntl_ModelForEachBox( pNtl, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize(pNtl->vObjs)) && (((pObj) = Vec_PtrEntry(pNtl->vObjs, i)), 1); i++ ) \ + if ( !Ntl_ObjIsBox(pObj) ) {} else +#define Ntl_ModelForEachNet( pNtl, pNet, i ) \ + for ( i = 0; i < pNtl->nTableSize; i++ ) \ + for ( pNet = pNtl->pTable[i]; pNet; pNet = pNet->pNext ) + +#define Ntl_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < (pObj)->nFanins) && ((pFanin) = (pObj)->pFanio[i]); i++ ) +#define Ntl_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; (i < (pObj)->nFanouts) && ((pFanout) = (pObj)->pFanio[(pObj)->nFanins+i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ntlAig.c ==========================================================*/ +extern Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode ); +extern int Ntl_ManExtract( Ntl_Man_t * p ); +extern int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping ); +extern int Ntl_ManInsertTest( Ntl_Man_t * p ); +extern int Ntl_ManInsertTestFpga( Ntl_Man_t * p ); +extern int Ntl_ManInsertTestIf( Ntl_Man_t * p ); +/*=== ntlCheck.c ==========================================================*/ +extern int Ntl_ManCheck( Ntl_Man_t * pMan ); +extern int Ntl_ModelCheck( Ntl_Mod_t * pModel ); +extern void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel ); +/*=== ntlDfs.c ==========================================================*/ +extern int Ntl_ManDfs( Ntl_Man_t * p ); +/*=== ntlMan.c ============================================================*/ +extern Ntl_Man_t * Ntl_ManAlloc( char * pFileName ); +extern void Ntl_ManFree( Ntl_Man_t * p ); +extern Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName ); +extern void Ntl_ManPrintStats( Ntl_Man_t * p ); +extern Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ); +extern void Ntl_ModelFree( Ntl_Mod_t * p ); +/*=== ntlMap.c ============================================================*/ +extern Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars ); +extern Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p ); +extern Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p ); +extern Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p ); +/*=== ntlObj.c ============================================================*/ +extern Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel ); +extern Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ); +extern Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel ); +extern Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins ); +extern Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts ); +extern char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName ); +extern char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop ); +extern char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName ); +/*=== ntlTable.c ==========================================================*/ +extern Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName ); +extern Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName ); +extern int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); +extern int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber ); +/*=== ntlTime.c ==========================================================*/ +extern Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ); +/*=== ntlReadBlif.c ==========================================================*/ +extern Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ); +/*=== ntlWriteBlif.c ==========================================================*/ +extern void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/src/aig/ntl/ntlAig.c b/src/aig/ntl/ntlAig.c new file mode 100644 index 00000000..c0a122d3 --- /dev/null +++ b/src/aig/ntl/ntlAig.c @@ -0,0 +1,596 @@ +/**CFile**************************************************************** + + FileName [ntlAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Netlist SOP to AIG conversion.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" +#include "dec.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Ntl_SopForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) +#define Ntl_CubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_SopIsConst0( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '0'; +} + +/**Function************************************************************* + + Synopsis [Reads the number of variables in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_SopGetVarNum( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur != '\n'; pCur++ ); + return pCur - pSop - 2; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_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 [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_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 [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_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 [Creates the constant 1 cover with the given number of variables and cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_SopStart( Aig_MmFlex_t * pMan, int nCubes, int nVars ) +{ + char * pSopCover, * pCube; + int i, Length; + + Length = nCubes * (nVars + 3); + pSopCover = Aig_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 cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_SopCreateFromIsop( Aig_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 = Ntl_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 [Transforms truth table into the SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_SopFromTruth( Ntl_Man_t * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ) +{ + char * pSop; + int RetValue; + if ( Kit_TruthIsConst0(pTruth, nVars) ) + return Ntl_ManStoreSop( p, " 0\n" ); + if ( Kit_TruthIsConst1(pTruth, nVars) ) + return Ntl_ManStoreSop( p, " 1\n" ); + RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); // 1 ); + assert( RetValue == 0 || RetValue == 1 ); + pSop = Ntl_SopCreateFromIsop( p->pMemSops, nVars, vCover ); + if ( RetValue ) + Ntl_SopComplement( pSop ); + return pSop; +} + + + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ntl_ConvertSopToAigInternal( Aig_Man_t * pMan, Ntl_Obj_t * pNode, char * pSop ) +{ + Ntl_Net_t * pNet; + Aig_Obj_t * pAnd, * pSum; + int i, Value, nFanins; + char * pCube; + // get the number of variables + nFanins = Ntl_SopGetVarNum(pSop); + // go through the cubes of the node's SOP + pSum = Aig_ManConst0(pMan); + Ntl_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Aig_ManConst1(pMan); + Ntl_CubeForEachVar( pCube, Value, i ) + { + pNet = Ntl_ObjFanin( pNode, i ); + if ( Value == '1' ) + pAnd = Aig_And( pMan, pAnd, pNet->pFunc ); + else if ( Value == '0' ) + pAnd = Aig_And( pMan, pAnd, Aig_Not(pNet->pFunc) ); + } + // add to the sum of cubes + pSum = Aig_Or( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Ntl_SopIsComplement(pSop) ) + pSum = Aig_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ntl_GraphToNetworkAig( Aig_Man_t * pMan, Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + Aig_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Aig_NotCond( Aig_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Aig_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Aig_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Ntl_ManExtractAigNode( Ntl_Obj_t * pNode ) +{ + Aig_Man_t * pMan = pNode->pModel->pMan->pAig; + int fUseFactor = 0; + // consider the constant node + if ( Ntl_SopGetVarNum(pNode->pSop) == 0 ) + return Aig_NotCond( Aig_ManConst1(pMan), Ntl_SopIsConst0(pNode->pSop) ); + // decide when to use factoring + if ( fUseFactor && Ntl_SopGetVarNum(pNode->pSop) > 2 && Ntl_SopGetCubeNum(pNode->pSop) > 1 ) + { + Dec_Graph_t * pFForm; + Dec_Node_t * pFFNode; + Aig_Obj_t * pFunc; + int i; + // perform factoring + pFForm = Dec_Factor( pNode->pSop ); + // collect the fanins + Dec_GraphForEachLeaf( pFForm, pFFNode, i ) + pFFNode->pFunc = Ntl_ObjFanin(pNode, i)->pFunc; + // perform strashing + pFunc = Ntl_GraphToNetworkAig( pMan, pFForm ); + Dec_GraphFree( pFForm ); + return pFunc; + } + return Ntl_ConvertSopToAigInternal( pMan, pNode, pNode->pSop ); +} + + + + +/**Function************************************************************* + + Synopsis [Extracts AIG from the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManExtract_old( Ntl_Man_t * p ) +{ + Ntl_Obj_t * pNode; + Ntl_Net_t * pNet; + int i; + // check the DFS traversal + if ( !Ntl_ManDfs( p ) ) + return 0; + // start the AIG manager + assert( p->pAig == NULL ); + p->pAig = Aig_ManStart( 10000 ); + // create the primary inputs + Ntl_ManForEachCiNet( p, pNet, i ) + pNet->pFunc = Aig_ObjCreatePi( p->pAig ); + // convert internal nodes to AIGs + Ntl_ManForEachNode( p, pNode, i ) + Ntl_ObjFanout0(pNode)->pFunc = Ntl_ManExtractAigNode( pNode ); + // create the primary outputs + Ntl_ManForEachCoNet( p, pNet, i ) + Aig_ObjCreatePo( p->pAig, pNet->pFunc ); + // cleanup the AIG + Aig_ManCleanup( p->pAig ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Extracts AIG from the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManExtract( Ntl_Man_t * p ) +{ + // start the AIG manager + assert( p->pAig == NULL ); + p->pAig = Aig_ManStart( 10000 ); + // check the DFS traversal + if ( !Ntl_ManDfs( p ) ) + return 0; + // cleanup the AIG + Aig_ManCleanup( p->pAig ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Inserts the given mapping into the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping ) +{ + char Buffer[100]; + Vec_Ptr_t * vCopies; + Vec_Int_t * vCover; + Ntl_Mod_t * pRoot; + Ntl_Obj_t * pNode; + Ntl_Net_t * pNet, * pNetCo; + Ntl_Lut_t * pLut; + int i, k, nDigits; + // remove old nodes + pRoot = Vec_PtrEntry( p->vModels, 0 ); + Ntl_ModelForEachNode( pRoot, pNode, i ) + Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL ); + // start mapping of AIG nodes into their copies + vCopies = Vec_PtrStart( Aig_ManObjNumMax(p->pAig) ); + Ntl_ManForEachCiNet( p, pNet, i ) + Vec_PtrWriteEntry( vCopies, pNet->pFunc->Id, pNet ); + // create a new node for each LUT + vCover = Vec_IntAlloc( 1 << 16 ); + nDigits = Aig_Base10Log( Vec_PtrSize(vMapping) ); + Vec_PtrForEachEntry( vMapping, pLut, i ) + { + pNode = Ntl_ModelCreateNode( pRoot, pLut->nFanins ); + pNode->pSop = Ntl_SopFromTruth( p, pLut->pTruth, pLut->nFanins, vCover ); + if ( !Kit_TruthIsConst0(pLut->pTruth, pLut->nFanins) && !Kit_TruthIsConst1(pLut->pTruth, pLut->nFanins) ) + { + for ( k = 0; k < pLut->nFanins; k++ ) + { + pNet = Vec_PtrEntry( vCopies, pLut->pFanins[k] ); + if ( pNet == NULL ) + { + printf( "Ntl_ManInsert(): Internal error: Net not found.\n" ); + return 0; + } + Ntl_ObjSetFanin( pNode, pNet, k ); + } + } + sprintf( Buffer, "lut%0*d", nDigits, i ); + if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) + { + printf( "Ntl_ManInsert(): Internal error: Intermediate net name is not unique.\n" ); + return 0; + } + pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); + if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) + { + printf( "Ntl_ManInsert(): Internal error: Net has more than one fanin.\n" ); + return 0; + } + Vec_PtrWriteEntry( vCopies, pLut->Id, pNet ); + } + Vec_IntFree( vCover ); + // mark CIs and outputs of the registers + Ntl_ManForEachCiNet( p, pNetCo, i ) + pNetCo->nVisits = 101; + // update the CO pointers + Ntl_ManForEachCoNet( p, pNetCo, i ) + { + if ( pNetCo->nVisits == 101 ) + continue; + pNetCo->nVisits = 101; + pNet = Vec_PtrEntry( vCopies, Aig_Regular(pNetCo->pFunc)->Id ); + pNode = Ntl_ModelCreateNode( pRoot, 1 ); + pNode->pSop = Aig_IsComplement(pNetCo->pFunc)? Ntl_ManStoreSop( p, "0 1\n" ) : Ntl_ManStoreSop( p, "1 1\n" ); + Ntl_ObjSetFanin( pNode, pNet, 0 ); + // update the CO driver net + pNetCo->pDriver = NULL; + if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) ) + { + printf( "Ntl_ManInsert(): Internal error: PO net has more than one fanin.\n" ); + return 0; + } + } + Vec_PtrFree( vCopies ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Extracts AIG from the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManPerformSynthesis( Ntl_Man_t * p ) +{ + extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); + extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); + Aig_Man_t * pTemp; + Ntl_Net_t * pNet; + int i; + // perform synthesis +printf( "Pre-synthesis AIG: " ); +Aig_ManPrintStats( p->pAig ); +// p->pAig = Dar_ManBalance( pTemp = p->pAig, 1 ); + p->pAig = Dar_ManCompress( pTemp = p->pAig, 1, 1, 0 ); + Ntl_ManForEachCiNet( p, pNet, i ) + pNet->pFunc = Aig_ManPi( p->pAig, i ); + Ntl_ManForEachCoNet( p, pNet, i ) + pNet->pFunc = Aig_ObjChild0( Aig_ManPo( p->pAig, i ) ); + Aig_ManStop( pTemp ); +printf( "Post-synthesis AIG: " ); +Aig_ManPrintStats( p->pAig ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Testing procedure for insertion of mapping into the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManInsertTest( Ntl_Man_t * p ) +{ + Vec_Ptr_t * vMapping; + int RetValue; + if ( !Ntl_ManExtract( p ) ) + return 0; + assert( p->pAig != NULL ); + Ntl_ManPerformSynthesis( p ); + vMapping = Ntl_MappingFromAig( p->pAig ); + RetValue = Ntl_ManInsert( p, vMapping ); + Vec_PtrFree( vMapping ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Testing procedure for insertion of mapping into the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManInsertTestIf( Ntl_Man_t * p ) +{ + Vec_Ptr_t * vMapping; + int RetValue; + if ( !Ntl_ManExtract( p ) ) + return 0; + assert( p->pAig != NULL ); +// Ntl_ManPerformSynthesis( p ); + vMapping = Ntl_MappingIf( p, p->pAig ); + RetValue = Ntl_ManInsert( p, vMapping ); + Vec_PtrFree( vMapping ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlCheck.c b/src/aig/ntl/ntlCheck.c new file mode 100644 index 00000000..d01c7d5e --- /dev/null +++ b/src/aig/ntl/ntlCheck.c @@ -0,0 +1,126 @@ +/**CFile**************************************************************** + + FileName [ntlCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Checks consistency of the netlist.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManCheck( Ntl_Man_t * pMan ) +{ + // check that the models have unique names + // check that the models (except the first one) do not have boxes + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ModelCheck( Ntl_Mod_t * pModel ) +{ + return 1; +} + + +/**Function************************************************************* + + Synopsis [Reads the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel ) +{ + Vec_Ptr_t * vNets; + Ntl_Net_t * pNet; + Ntl_Obj_t * pNode; + int i; + + if ( Ntl_ModelIsBlackBox(pModel) ) + return; + + // check for non-driven nets + vNets = Vec_PtrAlloc( 100 ); + Ntl_ModelForEachNet( pModel, pNet, i ) + { + if ( pNet->pDriver != NULL ) + continue; + // add the constant 0 driver + pNode = Ntl_ModelCreateNode( pModel, 0 ); + pNode->pSop = Ntl_ManStoreSop( pModel->pMan, " 0\n" ); + Ntl_ModelSetNetDriver( pNode, pNet ); + // add the net to those for which the warning will be printed + Vec_PtrPush( vNets, pNet ); + } + + // print the warning + if ( Vec_PtrSize(vNets) > 0 ) + { + printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pModel->pName ); + Vec_PtrForEachEntry( vNets, pNet, i ) + { + printf( "%s%s", (i? ", ": ""), pNet->pName ); + if ( i == 3 ) + { + if ( Vec_PtrSize(vNets) > 3 ) + printf( " ..." ); + break; + } + } + printf( "\n" ); + } + Vec_PtrFree( vNets ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlDfs.c b/src/aig/ntl/ntlDfs.c new file mode 100644 index 00000000..1e9503a4 --- /dev/null +++ b/src/aig/ntl/ntlDfs.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [ntlDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [DFS traversal.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Collects the nodes in a topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManDfs_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ) +{ + Ntl_Obj_t * pObj; + Ntl_Net_t * pNetFanin; + int i; + // skip visited + if ( pNet->nVisits == 2 ) + return 1; + // if the node is on the path, this is a combinational loop + if ( pNet->nVisits == 1 ) + return 0; + // mark the node as the one on the path + pNet->nVisits = 1; + // derive the box + pObj = pNet->pDriver; + assert( Ntl_ObjIsNode(pObj) || Ntl_ObjIsBox(pObj) ); + // visit the input nets of the box + Ntl_ObjForEachFanin( pObj, pNetFanin, i ) + if ( !Ntl_ManDfs_rec( p, pNetFanin ) ) + return 0; + // add box inputs/outputs to COs/CIs + if ( Ntl_ObjIsBox(pObj) ) + { + int LevelCur, LevelMax = -AIG_INFINITY; + Vec_IntPush( p->vBox1Cos, Aig_ManPoNum(p->pAig) ); + Ntl_ObjForEachFanin( pObj, pNetFanin, i ) + { + LevelCur = Aig_ObjLevel( Aig_Regular(pNetFanin->pFunc) ); + LevelMax = AIG_MAX( LevelMax, LevelCur ); + Vec_PtrPush( p->vCos, pNetFanin ); + Aig_ObjCreatePo( p->pAig, pNetFanin->pFunc ); + } + Ntl_ObjForEachFanout( pObj, pNetFanin, i ) + { + Vec_PtrPush( p->vCis, pNetFanin ); + pNetFanin->pFunc = Aig_ObjCreatePi( p->pAig ); + Aig_ObjSetLevel( pNetFanin->pFunc, LevelMax + 1 ); + } +//printf( "Creating fake PO with ID = %d.\n", Aig_ManPo(p->pAig, Vec_IntEntryLast(p->vBox1Cos))->Id ); + } + // store the node + Vec_PtrPush( p->vNodes, pObj ); + if ( Ntl_ObjIsNode(pObj) ) + pNet->pFunc = Ntl_ManExtractAigNode( pObj ); + pNet->nVisits = 2; + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs DFS.] + + Description [Checks for combinational loops. Collects PI/PO nets. + Collects nodes in the topological order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManDfs( Ntl_Man_t * p ) +{ + Ntl_Mod_t * pRoot; + Ntl_Obj_t * pObj; + Ntl_Net_t * pNet; + int i, nUselessObjects; + assert( Vec_PtrSize(p->vCis) == 0 ); + assert( Vec_PtrSize(p->vCos) == 0 ); + assert( Vec_PtrSize(p->vNodes) == 0 ); + assert( Vec_IntSize(p->vBox1Cos) == 0 ); + // get the root model + pRoot = Vec_PtrEntry( p->vModels, 0 ); + // collect primary inputs + Ntl_ModelForEachPi( pRoot, pObj, i ) + { + assert( Ntl_ObjFanoutNum(pObj) == 1 ); + pNet = Ntl_ObjFanout0(pObj); + Vec_PtrPush( p->vCis, pNet ); + pNet->pFunc = Aig_ObjCreatePi( p->pAig ); + if ( pNet->nVisits ) + { + printf( "Ntl_ManDfs(): Primary input appears twice in the list.\n" ); + return 0; + } + pNet->nVisits = 2; + } + // collect latch outputs + Ntl_ModelForEachLatch( pRoot, pObj, i ) + { + assert( Ntl_ObjFanoutNum(pObj) == 1 ); + pNet = Ntl_ObjFanout0(pObj); + Vec_PtrPush( p->vCis, pNet ); + pNet->pFunc = Aig_ObjCreatePi( p->pAig ); + if ( pNet->nVisits ) + { + printf( "Ntl_ManDfs(): Latch output is duplicated or defined as a primary input.\n" ); + return 0; + } + pNet->nVisits = 2; + } + // visit the nodes starting from primary outputs + Ntl_ModelForEachPo( pRoot, pObj, i ) + { + pNet = Ntl_ObjFanin0(pObj); + if ( !Ntl_ManDfs_rec( p, pNet ) ) + { + printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" ); + Vec_PtrClear( p->vCis ); + Vec_PtrClear( p->vCos ); + Vec_PtrClear( p->vNodes ); + return 0; + } + Vec_PtrPush( p->vCos, pNet ); + Aig_ObjCreatePo( p->pAig, pNet->pFunc ); + } + // visit the nodes starting from latch inputs outputs + Ntl_ModelForEachLatch( pRoot, pObj, i ) + { + pNet = Ntl_ObjFanin0(pObj); + if ( !Ntl_ManDfs_rec( p, pNet ) ) + { + printf( "Ntl_ManDfs(): Error: Combinational loop is detected.\n" ); + Vec_PtrClear( p->vCis ); + Vec_PtrClear( p->vCos ); + Vec_PtrClear( p->vNodes ); + return 0; + } + Vec_PtrPush( p->vCos, pNet ); + Aig_ObjCreatePo( p->pAig, pNet->pFunc ); + } + // report the number of dangling objects + nUselessObjects = Ntl_ModelNodeNum(pRoot) + Ntl_ModelBoxNum(pRoot) - Vec_PtrSize(p->vNodes); + if ( nUselessObjects ) + printf( "The number of nodes that do not feed into POs = %d.\n", nUselessObjects ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c new file mode 100644 index 00000000..9b4aff5f --- /dev/null +++ b/src/aig/ntl/ntlMan.c @@ -0,0 +1,196 @@ +/**CFile**************************************************************** + + FileName [ntlMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Netlist manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the netlist manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Man_t * Ntl_ManAlloc( char * pFileName ) +{ + Ntl_Man_t * p; + // start the manager + p = ALLOC( Ntl_Man_t, 1 ); + memset( p, 0, sizeof(Ntl_Man_t) ); + p->vModels = Vec_PtrAlloc( 1000 ); + p->vCis = Vec_PtrAlloc( 1000 ); + p->vCos = Vec_PtrAlloc( 1000 ); + p->vNodes = Vec_PtrAlloc( 1000 ); + p->vBox1Cos = Vec_IntAlloc( 1000 ); + // start the manager + p->pMemObjs = Aig_MmFlexStart(); + p->pMemSops = Aig_MmFlexStart(); + // same the names + p->pName = Ntl_ManStoreFileName( p, pFileName ); + p->pSpec = Ntl_ManStoreName( p, pFileName ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the netlist manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ManFree( Ntl_Man_t * p ) +{ + if ( p->vModels ) + { + Ntl_Mod_t * pModel; + int i; + Ntl_ManForEachModel( p, pModel, i ) + Ntl_ModelFree( pModel ); + Vec_PtrFree( p->vModels ); + } + if ( p->vCis ) Vec_PtrFree( p->vCis ); + if ( p->vCos ) Vec_PtrFree( p->vCos ); + if ( p->vNodes ) Vec_PtrFree( p->vNodes ); + if ( p->vBox1Cos ) Vec_IntFree( p->vBox1Cos ); + if ( p->pMemObjs ) Aig_MmFlexStop( p->pMemObjs, 0 ); + if ( p->pMemSops ) Aig_MmFlexStop( p->pMemSops, 0 ); + if ( p->pAig ) Aig_ManStop( p->pAig ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Find the model with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Mod_t * Ntl_ManFindModel( Ntl_Man_t * p, char * pName ) +{ + Ntl_Mod_t * pModel; + int i; + Vec_PtrForEachEntry( p->vModels, pModel, i ) + if ( !strcmp( pModel->pName, pName ) ) + return pModel; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Deallocates the netlist manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ManPrintStats( Ntl_Man_t * p ) +{ + Ntl_Mod_t * pRoot; + pRoot = Vec_PtrEntry( p->vModels, 0 ); + printf( "%-15s : ", p->pName ); + printf( "pi = %5d ", Ntl_ModelPiNum(pRoot) ); + printf( "po = %5d ", Ntl_ModelPoNum(pRoot) ); + printf( "latch = %5d ", Ntl_ModelLatchNum(pRoot) ); + printf( "node = %5d ", Ntl_ModelNodeNum(pRoot) ); + printf( "box = %4d ", Ntl_ModelBoxNum(pRoot) ); + printf( "model = %3d", Vec_PtrSize(p->vModels) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Allocates the model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ) +{ + Ntl_Mod_t * p; + // start the manager + p = ALLOC( Ntl_Mod_t, 1 ); + memset( p, 0, sizeof(Ntl_Mod_t) ); + p->pMan = pMan; + p->pName = Ntl_ManStoreName( p->pMan, pName ); + Vec_PtrPush( pMan->vModels, p ); + p->vObjs = Vec_PtrAlloc( 10000 ); + p->vPis = Vec_PtrAlloc( 1000 ); + p->vPos = Vec_PtrAlloc( 1000 ); + // start the table + p->nTableSize = Aig_PrimeCudd( 10000 ); + p->pTable = ALLOC( Ntl_Net_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Ntl_Net_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ModelFree( Ntl_Mod_t * p ) +{ + if ( p->vRequireds ) Vec_IntFree( p->vRequireds ); + if ( p->vArrivals ) Vec_IntFree( p->vArrivals ); + if ( p->vDelays ) Vec_IntFree( p->vDelays ); + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + free( p->pTable ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlMap.c b/src/aig/ntl/ntlMap.c new file mode 100644 index 00000000..59c40453 --- /dev/null +++ b/src/aig/ntl/ntlMap.c @@ -0,0 +1,624 @@ +/**CFile**************************************************************** + + FileName [ntlMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Derives mapped network from AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates mapping for the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_MappingAlloc( int nLuts, int nVars ) +{ + char * pMemory; + Ntl_Lut_t ** pArray; + int nEntrySize, i; + nEntrySize = sizeof(Ntl_Lut_t) + sizeof(int) * nVars + sizeof(unsigned) * Aig_TruthWordNum(nVars); + pArray = (Ntl_Lut_t **)malloc( (sizeof(Ntl_Lut_t *) + nEntrySize) * nLuts ); + pMemory = (char *)(pArray + nLuts); + memset( pMemory, 0, nEntrySize * nLuts ); + for ( i = 0; i < nLuts; i++ ) + { + pArray[i] = (Ntl_Lut_t *)pMemory; + pArray[i]->pFanins = (int *)(pMemory + sizeof(Ntl_Lut_t)); + pArray[i]->pTruth = (unsigned *)(pMemory + sizeof(Ntl_Lut_t) + sizeof(int) * nVars); + pMemory += nEntrySize; + } + return Vec_PtrAllocArray( (void **)pArray, nLuts ); +} + +/**Function************************************************************* + + Synopsis [Derives trivial mapping from the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_MappingFromAig( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMapping; + Ntl_Lut_t * pLut; + Aig_Obj_t * pObj; + int i, k = 0, nBytes = 4; + vMapping = Ntl_MappingAlloc( Aig_ManAndNum(p) + (int)(Aig_ManConst1(p)->nRefs > 0), 2 ); + if ( Aig_ManConst1(p)->nRefs > 0 ) + { + pLut = Vec_PtrEntry( vMapping, k++ ); + pLut->Id = 0; + pLut->nFanins = 0; + memset( pLut->pTruth, 0xFF, nBytes ); + } + Aig_ManForEachNode( p, pObj, i ) + { + pLut = Vec_PtrEntry( vMapping, k++ ); + pLut->Id = pObj->Id; + pLut->nFanins = 2; + pLut->pFanins[0] = Aig_ObjFaninId0(pObj); + pLut->pFanins[1] = Aig_ObjFaninId1(pObj); + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + memset( pLut->pTruth, 0x11, nBytes ); + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + memset( pLut->pTruth, 0x22, nBytes ); + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + memset( pLut->pTruth, 0x44, nBytes ); + else if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + memset( pLut->pTruth, 0x88, nBytes ); + } + assert( k == Vec_PtrSize(vMapping) ); + return vMapping; +} + + +#include "fpgaInt.h" + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ntl_FpgaComputeTruth_rec( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars, int * pnCounter ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + assert( !Fpga_IsComplement(pCut) ); + // if the cut is visited, return the result + if ( pCut->pRoot ) + return (unsigned *)pCut->pRoot; + // compute the functions of the children + pTruth0 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pOne), vTruthElem, vTruthStore, vVisited, nVars, pnCounter ); + if ( Fpga_CutIsComplement(pCut->pOne) ) + Kit_TruthNot( pTruth0, pTruth0, nVars ); + pTruth1 = Ntl_FpgaComputeTruth_rec( Fpga_CutRegular(pCut->pTwo), vTruthElem, vTruthStore, vVisited, nVars, pnCounter ); + if ( Fpga_CutIsComplement(pCut->pTwo) ) + Kit_TruthNot( pTruth1, pTruth1, nVars ); + // get the function of the cut + pTruth = Vec_PtrEntry( vTruthStore, (*pnCounter)++ ); + Kit_TruthAnd( pTruth, pTruth0, pTruth1, nVars ); + if ( pCut->Phase ) + Kit_TruthNot( pTruth, pTruth, nVars ); + assert( pCut->pRoot == NULL ); + pCut->pRoot = (Fpga_Node_t *)pTruth; + // add this cut to the visited list + Vec_PtrPush( vVisited, pCut ); + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ntl_FpgaComputeTruth( Fpga_Cut_t * pCut, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore, Vec_Ptr_t * vVisited, int nVars ) +{ + unsigned * pTruth; + int i, nCounter = 0; + assert( pCut->nLeaves > 1 ); + // set the leaf variables + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->pRoot = (Fpga_Node_t *)Vec_PtrEntry( vTruthElem, i ); + // recursively compute the function + Vec_PtrClear( vVisited ); + pTruth = Ntl_FpgaComputeTruth_rec( pCut, vTruthElem, vTruthStore, vVisited, nVars, &nCounter ); + // clean the intermediate BDDs + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->pRoot = NULL; + Vec_PtrForEachEntry( vVisited, pCut, i ) + pCut->pRoot = NULL; + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Man_t * Ntl_ManToFpga( Aig_Man_t * p ) +{ + Fpga_Man_t * pMan; + Aig_Obj_t * pNode;//, * pFanin, * pPrev; + float * pfArrivals; + int i; + // start the mapping manager and set its parameters + pMan = Fpga_ManCreate( Aig_ManPiNum(p), Aig_ManPoNum(p), 0 ); + if ( pMan == NULL ) + return NULL; + // set the arrival times + pfArrivals = ALLOC( float, Aig_ManPiNum(p) ); + memset( pfArrivals, 0, sizeof(float) * Aig_ManPiNum(p) ); + Fpga_ManSetInputArrivals( pMan, pfArrivals ); + // create PIs and remember them in the old nodes + Aig_ManConst1(p)->pData = Fpga_ManReadConst1(pMan); + Aig_ManForEachPi( p, pNode, i ) + pNode->pData = Fpga_ManReadInputs(pMan)[i]; + // load the AIG into the mapper + Aig_ManForEachNode( p, pNode, i ) + { + pNode->pData = Fpga_NodeAnd( pMan, + Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), + Fpga_NotCond( Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); + // set up the choice node +// if ( Aig_AigNodeIsChoice( pNode ) ) +// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) +// { +// Fpga_NodeSetNextE( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); +// Fpga_NodeSetRepr( (If_Obj_t *)pFanin->pData, (If_Obj_t *)pNode->pData ); +// } + } + // set the primary outputs while copying the phase + Aig_ManForEachPo( p, pNode, i ) + Fpga_ManReadOutputs(pMan)[i] = Fpga_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ); + assert( Fpga_NodeVecReadSize(pMan->vAnds) == Aig_ManNodeNum(p) ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_ManFromFpga( Aig_Man_t * p, Fpga_Man_t * pMan ) +{ + Fpga_NodeVec_t * vFpgaMap; + Fpga_Node_t ** ppLeaves, * pNode; + Fpga_Cut_t * pCutBest; + Vec_Ptr_t * vTruthElem, * vTruthStore, * vVisited, * vMapping; + Vec_Int_t * vFpgaToAig; + Aig_Obj_t * pObj; + Ntl_Lut_t * pLut; + unsigned * pTruth; + int i, k, nLuts, nLeaves, nWords, nVarsMax; + // create mapping of FPGA nodes into AIG nodes + vFpgaToAig = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_IntFill( vFpgaToAig, Aig_ManObjNumMax(p), -1 ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + continue; + if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL ) + continue; + pNode = pObj->pData; + assert( pNode != NULL ); + Vec_IntWriteEntry( vFpgaToAig, Fpga_NodeReadNum(pNode), pObj->Id ); + } + // create the mapping + + + // make sure nodes are in the top order!!! + + + nVarsMax = Fpga_ManReadVarMax( pMan ); + nWords = Aig_TruthWordNum( nVarsMax ); + vFpgaMap = Fpga_ManReadMapping( pMan ); + vMapping = Ntl_MappingAlloc( vFpgaMap->nSize + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax ); + nLuts = 0; + if ( Aig_ManConst1(p)->nRefs > 0 ) + { + pLut = Vec_PtrEntry( vMapping, nLuts++ ); + pLut->Id = 0; + pLut->nFanins = 0; + memset( pLut->pTruth, 0xFF, 4 * nWords ); + } + vVisited = Vec_PtrAlloc( 1000 ); + vTruthElem = Vec_PtrAllocTruthTables( nVarsMax ); + vTruthStore = Vec_PtrAllocSimInfo( 256, nWords ); + for ( i = 0; i < vFpgaMap->nSize; i++ ) + { + // get the best cut + pNode = vFpgaMap->pArray[i]; + pCutBest = Fpga_NodeReadCutBest( pNode ); + nLeaves = Fpga_CutReadLeavesNum( pCutBest ); + ppLeaves = Fpga_CutReadLeaves( pCutBest ); + // fill the LUT + pLut = Vec_PtrEntry( vMapping, nLuts++ ); + pLut->Id = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(pNode) ); + pLut->nFanins = nLeaves; + for ( k = 0; k < nLeaves; k++ ) + pLut->pFanins[k] = Vec_IntEntry( vFpgaToAig, Fpga_NodeReadNum(ppLeaves[k]) ); + // compute the truth table + pTruth = Ntl_FpgaComputeTruth( pCutBest, vTruthElem, vTruthStore, vVisited, nVarsMax ); + memcpy( pLut->pTruth, pTruth, 4 * nWords ); + } + assert( nLuts == Vec_PtrSize(vMapping) ); + Vec_IntFree( vFpgaToAig ); + Vec_PtrFree( vVisited ); + Vec_PtrFree( vTruthElem ); + Vec_PtrFree( vTruthStore ); + return vMapping; +} + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_MappingFpga( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMapping; + Fpga_Man_t * pMan; + // print a warning about choice nodes + if ( p->pEquivs ) + printf( "Ntl_MappingFpga(): Performing FPGA mapping with choices.\n" ); + // perform FPGA mapping + pMan = Ntl_ManToFpga( p ); + if ( pMan == NULL ) + return NULL; + if ( !Fpga_Mapping( pMan ) ) + { + Fpga_ManFree( pMan ); + return NULL; + } + // transform the result of mapping into a BDD network + vMapping = Ntl_ManFromFpga( p, pMan ); + Fpga_ManFree( pMan ); + if ( vMapping == NULL ) + return NULL; + return vMapping; +} + + + + +#include "if.h" + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_ManSetIfParsDefault( If_Par_t * pPars ) +{ +// extern void * Abc_FrameReadLibLut(); + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters +// pPars->nLutSize = -1; + pPars->nLutSize = 6; + pPars->nCutsMax = 8; + pPars->nFlowIters = 1; + pPars->nAreaIters = 2; + pPars->DelayTarget = -1; + pPars->fPreprocess = 1; + pPars->fArea = 0; + pPars->fFancy = 0; + pPars->fExpRed = 0; + pPars->fLatchPaths = 0; + pPars->fEdge = 1; + pPars->fCutMin = 1; + pPars->fSeqMap = 0; + pPars->fVerbose = 1; + // internal parameters + pPars->fTruth = 1; + pPars->nLatches = 0; + pPars->fLiftLeaves = 0; +// pPars->pLutLib = Abc_FrameReadLibLut(); + pPars->pLutLib = NULL; + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->pFuncCost = NULL; +/* + if ( pPars->nLutSize == -1 ) + { + if ( pPars->pLutLib == NULL ) + { + printf( "The LUT library is not given.\n" ); + return; + } + // get LUT size from the library + pPars->nLutSize = pPars->pLutLib->LutMax; + } +*/ +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * Ntk_ManToIf_old( Aig_Man_t * p, If_Par_t * pPars ) +{ + If_Man_t * pIfMan; + Aig_Obj_t * pNode;//, * pFanin, * pPrev; + Vec_Ptr_t * vNodes; + int i; + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + // print warning about excessive memory usage + if ( 1.0 * Aig_ManObjNum(p) * 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 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) ); + // load the AIG into the mapper + vNodes = Aig_ManDfsPio( p ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Aig_ObjIsAnd(pNode) ) + pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan, + If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), + If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); + else if ( Aig_ObjIsPi(pNode) ) + pNode->pData = If_ManCreateCi( pIfMan ); + else if ( Aig_ObjIsPo(pNode) ) + If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); + else if ( Aig_ObjIsConst1(pNode) ) + Aig_ManConst1(p)->pData = If_ManConst1( pIfMan ); + else // add the node to the mapper + assert( 0 ); + // set up the choice node +// if ( Aig_AigNodeIsChoice( pNode ) ) +// { +// pIfMan->nChoices++; +// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) +// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); +// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); +// } + } + Vec_PtrFree( vNodes ); + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * Ntk_ManToIf( Aig_Man_t * p, If_Par_t * pPars ) +{ + If_Man_t * pIfMan; + Aig_Obj_t * pNode;//, * pFanin, * pPrev; + int i; + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + // print warning about excessive memory usage + if ( 1.0 * Aig_ManObjNum(p) * 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 * Aig_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Aig_ManObjNum(p) ); + // load the AIG into the mapper + Aig_ManForEachObj( p, pNode, i ) + { + if ( Aig_ObjIsAnd(pNode) ) + pNode->pData = (Aig_Obj_t *)If_ManCreateAnd( pIfMan, + If_NotCond( (If_Obj_t *)Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ), + If_NotCond( (If_Obj_t *)Aig_ObjFanin1(pNode)->pData, Aig_ObjFaninC1(pNode) ) ); + else if ( Aig_ObjIsPi(pNode) ) + { + pNode->pData = If_ManCreateCi( pIfMan ); + ((If_Obj_t *)pNode->pData)->Level = pNode->Level; + } + else if ( Aig_ObjIsPo(pNode) ) + If_ManCreateCo( pIfMan, If_NotCond( Aig_ObjFanin0(pNode)->pData, Aig_ObjFaninC0(pNode) ) ); + else if ( Aig_ObjIsConst1(pNode) ) + Aig_ManConst1(p)->pData = If_ManConst1( pIfMan ); + else // add the node to the mapper + assert( 0 ); + // set up the choice node +// if ( Aig_AigNodeIsChoice( pNode ) ) +// { +// pIfMan->nChoices++; +// for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) +// If_ObjSetChoice( (If_Obj_t *)pPrev->pData, (If_Obj_t *)pFanin->pData ); +// If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pData ); +// } + } + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntk_ManFromIf( Aig_Man_t * p, If_Man_t * pMan ) +{ + Vec_Ptr_t * vIfMap; + If_Obj_t * pNode, * pLeaf; + If_Cut_t * pCutBest; + Vec_Ptr_t * vMapping; + Vec_Int_t * vIfToAig; + Aig_Obj_t * pObj; + Ntl_Lut_t * pLut; + int * ppLeaves; + int i, k, nLuts, nLeaves, nWords, nVarsMax; + // create mapping of If nodes into AIG nodes + vIfToAig = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_IntFill( vIfToAig, Aig_ManObjNumMax(p), -1 ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + continue; + if ( Aig_ObjIsConst1(pObj) && pObj->pData == NULL ) + continue; + if ( Aig_ObjIsPi(pObj) && pObj->pData == NULL ) + continue; + pNode = pObj->pData; + assert( pNode != NULL ); + Vec_IntWriteEntry( vIfToAig, pNode->Id, pObj->Id ); + } + // create the mapping + vIfMap = If_ManCollectMappingDirect( pMan ); + nVarsMax = pMan->pPars->nLutSize; + nWords = Aig_TruthWordNum( nVarsMax ); + vMapping = Ntl_MappingAlloc( Vec_PtrSize(vIfMap) + (int)(Aig_ManConst1(p)->nRefs > 0), nVarsMax ); + nLuts = 0; + if ( Aig_ManConst1(p)->nRefs > 0 ) + { + pLut = Vec_PtrEntry( vMapping, nLuts++ ); + pLut->Id = 0; + pLut->nFanins = 0; + memset( pLut->pTruth, 0xFF, 4 * nWords ); + } + Vec_PtrForEachEntry( vIfMap, pNode, i ) + { + // get the best cut + pCutBest = If_ObjCutBest(pNode); + nLeaves = If_CutLeaveNum( pCutBest ); + ppLeaves = If_CutLeaves( pCutBest ); + // fill the LUT + pLut = Vec_PtrEntry( vMapping, nLuts++ ); + pLut->Id = Vec_IntEntry( vIfToAig, pNode->Id ); + pLut->nFanins = nLeaves; + If_CutForEachLeaf( pMan, pCutBest, pLeaf, k ) + pLut->pFanins[k] = Vec_IntEntry( vIfToAig, pLeaf->Id ); + // compute the truth table + memcpy( pLut->pTruth, If_CutTruth(pCutBest), 4 * nWords ); + } + assert( nLuts == Vec_PtrSize(vMapping) ); + Vec_IntFree( vIfToAig ); + Vec_PtrFree( vIfMap ); + return vMapping; +} + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_MappingIf( Ntl_Man_t * pMan, Aig_Man_t * p ) +{ + Vec_Ptr_t * vMapping; + If_Par_t Pars, * pPars = &Pars; + If_Man_t * pIfMan; + // perform FPGA mapping + Ntk_ManSetIfParsDefault( pPars ); + // set the arrival times + pPars->pTimesArr = ALLOC( float, Aig_ManPiNum(p) ); + memset( pPars->pTimesArr, 0, sizeof(float) * Aig_ManPiNum(p) ); + // translate into the mapper + pIfMan = Ntk_ManToIf( p, pPars ); + if ( pIfMan == NULL ) + return NULL; + pIfMan->pManTim = Ntl_ManCreateTiming( pMan ); + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + // transform the result of mapping into the new network + vMapping = Ntk_ManFromIf( p, pIfMan ); + If_ManStop( pIfMan ); + if ( vMapping == NULL ) + return NULL; + return vMapping; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlObj.c b/src/aig/ntl/ntlObj.c new file mode 100644 index 00000000..2e39fbbf --- /dev/null +++ b/src/aig/ntl/ntlObj.c @@ -0,0 +1,238 @@ +/**CFile**************************************************************** + + FileName [.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Obj_t * Ntl_ModelCreatePi( Ntl_Mod_t * pModel ) +{ + Ntl_Obj_t * p; + p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); + memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); + p->Id = Vec_PtrSize( pModel->vObjs ); + Vec_PtrPush( pModel->vObjs, p ); + Vec_PtrPush( pModel->vPis, p ); + p->pModel = pModel; + p->Type = NTL_OBJ_PI; + p->nFanins = 0; + p->nFanouts = 1; + pModel->nObjs[NTL_OBJ_PI]++; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Obj_t * Ntl_ModelCreatePo( Ntl_Mod_t * pModel, Ntl_Net_t * pNet ) +{ + Ntl_Obj_t * p; + p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); + memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) ); + p->Id = Vec_PtrSize( pModel->vObjs ); + Vec_PtrPush( pModel->vObjs, p ); + Vec_PtrPush( pModel->vPos, p ); + p->pModel = pModel; + p->Type = NTL_OBJ_PO; + p->nFanins = 1; + p->nFanouts = 0; + p->pFanio[0] = pNet; + pModel->nObjs[NTL_OBJ_PO]++; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Obj_t * Ntl_ModelCreateLatch( Ntl_Mod_t * pModel ) +{ + Ntl_Obj_t * p; + p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 ); + memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * 3 ); + p->Id = Vec_PtrSize( pModel->vObjs ); + Vec_PtrPush( pModel->vObjs, p ); + p->pModel = pModel; + p->Type = NTL_OBJ_LATCH; + p->nFanins = 2; + p->nFanouts = 1; + pModel->nObjs[NTL_OBJ_LATCH]++; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Obj_t * Ntl_ModelCreateNode( Ntl_Mod_t * pModel, int nFanins ) +{ + Ntl_Obj_t * p; + p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) ); + memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + 1) ); + p->Id = Vec_PtrSize( pModel->vObjs ); + Vec_PtrPush( pModel->vObjs, p ); + p->pModel = pModel; + p->Type = NTL_OBJ_NODE; + p->nFanins = nFanins; + p->nFanouts = 1; + pModel->nObjs[NTL_OBJ_NODE]++; + return p; +} + +/**Function************************************************************* + + Synopsis [Create the latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Obj_t * Ntl_ModelCreateBox( Ntl_Mod_t * pModel, int nFanins, int nFanouts ) +{ + Ntl_Obj_t * p; + p = (Ntl_Obj_t *)Aig_MmFlexEntryFetch( pModel->pMan->pMemObjs, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) ); + memset( p, 0, sizeof(Ntl_Obj_t) + sizeof(Ntl_Net_t *) * (nFanins + nFanouts) ); + p->Id = Vec_PtrSize( pModel->vObjs ); + Vec_PtrPush( pModel->vObjs, p ); + p->pModel = pModel; + p->Type = NTL_OBJ_BOX; + p->nFanins = nFanins; + p->nFanouts = nFanouts; + pModel->nObjs[NTL_OBJ_BOX]++; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates memory and copies the name into it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_ManStoreName( Ntl_Man_t * p, char * pName ) +{ + char * pStore; + pStore = Aig_MmFlexEntryFetch( p->pMemObjs, strlen(pName) + 1 ); + strcpy( pStore, pName ); + return pStore; +} + +/**Function************************************************************* + + Synopsis [Allocates memory and copies the SOP into it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_ManStoreSop( Ntl_Man_t * p, char * pSop ) +{ + char * pStore; + pStore = Aig_MmFlexEntryFetch( p->pMemSops, strlen(pSop) + 1 ); + strcpy( pStore, pSop ); + return pStore; +} + +/**Function************************************************************* + + Synopsis [Allocates memory and copies the root of file name there.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ntl_ManStoreFileName( Ntl_Man_t * p, char * pFileName ) +{ + char * pBeg, * pEnd, * pStore, * pCur; + // find the first dot + for ( pEnd = pFileName; *pEnd; pEnd++ ) + if ( *pEnd == '.' ) + break; + // find the first char + for ( pBeg = pEnd - 1; pBeg >= pFileName; pBeg-- ) + if ( !((*pBeg >= 'a' && *pBeg <= 'z') || (*pBeg >= 'A' && *pBeg <= 'Z') || (*pBeg >= '0' && *pBeg <= '9') || *pBeg == '_') ) + break; + pBeg++; + // fill up storage + pStore = Aig_MmFlexEntryFetch( p->pMemSops, pEnd - pBeg + 1 ); + for ( pCur = pStore; pBeg < pEnd; pBeg++, pCur++ ) + *pCur = *pBeg; + *pCur = 0; + return pStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c new file mode 100644 index 00000000..d085b5e6 --- /dev/null +++ b/src/aig/ntl/ntlReadBlif.c @@ -0,0 +1,1163 @@ +/**CFile**************************************************************** + + FileName [ntlReadBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 8, 2007.] + + Revision [$Id: ntlReadBlif.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ioa_ReadMod_t_ Ioa_ReadMod_t; // parsing model +typedef struct Ioa_ReadMan_t_ Ioa_ReadMan_t; // parsing manager + +struct Ioa_ReadMod_t_ +{ + // file lines + char * pFirst; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latch lines + Vec_Ptr_t * vNames; // .names lines + Vec_Ptr_t * vSubckts; // .subckt lines + Vec_Ptr_t * vDelays; // .delay lines + Vec_Ptr_t * vArrivals; // .input_arrival lines + Vec_Ptr_t * vRequireds; // .output_required lines + int fBlackBox; // indicates blackbox model + // the resulting network + Ntl_Mod_t * pNtk; + // the parent manager + Ioa_ReadMan_t * pMan; +}; + +struct Ioa_ReadMan_t_ +{ + // general info about file + 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 + Ntl_Man_t * pDesign; // the design under construction + // intermediate storage for models + Vec_Ptr_t * vModels; // vector of models + Ioa_ReadMod_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 Ioa_ReadMan_t * Ioa_ReadAlloc(); +static void Ioa_ReadFree( Ioa_ReadMan_t * p ); +static Ioa_ReadMod_t * Ioa_ReadModAlloc(); +static void Ioa_ReadModFree( Ioa_ReadMod_t * p ); +static char * Ioa_ReadLoadFile( char * pFileName ); +static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p ); +static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ); +static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p ); +static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine ); +static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput ); +static int Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine ); + +static int Ioa_ReadCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } +static int Ioa_ReadCharIsSopSymb( char s ) { return s == '0' || s == '1' || s == '-' || s == '\r' || s == '\n'; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) +{ + FILE * pFile; + Ioa_ReadMan_t * p; + Ntl_Mod_t * pNtk; + Ntl_Man_t * pDesign; + int i; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ioa_ReadBlif(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Ioa_ReadAlloc(); + p->pFileName = pFileName; + p->pBuffer = Ioa_ReadLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Ioa_ReadFree( p ); + return NULL; + } + // set the design name + p->pDesign = Ntl_ManAlloc( pFileName ); + // prepare the file for parsing + Ioa_ReadReadPreparse( p ); + // parse interfaces of each network + if ( !Ioa_ReadReadInterfaces( p ) ) + { + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + Ioa_ReadFree( p ); + return NULL; + } + // construct the network + pDesign = Ioa_ReadParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pDesign == NULL ) + { + Ioa_ReadFree( p ); + return NULL; + } + p->pDesign = NULL; + Ioa_ReadFree( p ); +// pDesign should be linked to all models of the design + + // make sure that everything is okay with the network structure + if ( fCheck ) + { + // check individual models + Vec_PtrForEachEntry( pDesign->vModels, pNtk, i ) + { + if ( !Ntl_ModelCheck( pNtk ) ) + { + printf( "Ioa_ReadBlif: The network check has failed for network %s.\n", pNtk->pName ); + Ntl_ManFree( pDesign ); + return NULL; + } + } + // check the hierarchy + if ( !Ntl_ManCheck( pDesign ) ) + { + printf( "Ioa_ReadBlif: The hierarchy check has failed for design %s.\n", pDesign->pName ); + Ntl_ManFree( pDesign ); + return NULL; + } + + } +//Ioa_WriteBlif( pDesign, "_temp_.blif" ); + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Ioa_ReadMan_t * Ioa_ReadAlloc() +{ + Ioa_ReadMan_t * p; + p = ALLOC( Ioa_ReadMan_t, 1 ); + memset( p, 0, sizeof(Ioa_ReadMan_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 Ioa_ReadFree( Ioa_ReadMan_t * p ) +{ + Ioa_ReadMod_t * pMod; + int i; + if ( p->pDesign ) + Ntl_ManFree( p->pDesign ); + if ( p->pBuffer ) + free( p->pBuffer ); + if ( p->vLines ) + Vec_PtrFree( p->vLines ); + if ( p->vModels ) + { + Vec_PtrForEachEntry( p->vModels, pMod, i ) + Ioa_ReadModFree( 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 Ioa_ReadMod_t * Ioa_ReadModAlloc() +{ + Ioa_ReadMod_t * p; + p = ALLOC( Ioa_ReadMod_t, 1 ); + memset( p, 0, sizeof(Ioa_ReadMod_t) ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vSubckts = Vec_PtrAlloc( 512 ); + p->vDelays = Vec_PtrAlloc( 512 ); + p->vArrivals = Vec_PtrAlloc( 512 ); + p->vRequireds = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ioa_ReadModFree( Ioa_ReadMod_t * p ) +{ + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vSubckts ); + Vec_PtrFree( p->vDelays ); + Vec_PtrFree( p->vArrivals ); + Vec_PtrFree( p->vRequireds ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of given chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadCountChars( char * pLine, char Char ) +{ + char * pCur; + int Counter = 0; + for ( pCur = pLine; *pCur; pCur++ ) + if ( *pCur == Char ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ioa_ReadCollectTokens( 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 Ioa_ReadSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Ioa_ReadCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Ioa_ReadCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Ioa_ReadSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Ioa_ReadCharIsSpace(*pCur) || *pCur == Char ) + *pCur = 0; + // collect tokens + Ioa_ReadCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadGetLine( Ioa_ReadMan_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 * Ioa_ReadLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ioa_ReadLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Ioa_ReadLoadFile(): 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 Ioa_ReadReadPreparse( Ioa_ReadMan_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 ( !Ioa_ReadCharIsSpace(*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 ( Ioa_ReadCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) ) + Vec_PtrPush( p->pLatest->vNames, pCur ); + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->pLatest->vLatches, 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 ( !strncmp(pCur, "delay", 5) ) + Vec_PtrPush( p->pLatest->vDelays, pCur ); + else if ( !strncmp(pCur, "input_arrival", 13) ) + Vec_PtrPush( p->pLatest->vArrivals, pCur ); + else if ( !strncmp(pCur, "output_required", 15) ) + Vec_PtrPush( p->pLatest->vRequireds, pCur ); + else if ( !strncmp(pCur, "blackbox", 8) ) + p->pLatest->fBlackBox = 1; + else if ( !strncmp(pCur, "model", 5) ) + { + p->pLatest = Ioa_ReadModAlloc(); + p->pLatest->pFirst = 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", Ioa_ReadGetLine(p, pCur) ); + break; + } + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Ioa_ReadGetLine(p, pCur), pCur ); + } + } +} + +/**Function************************************************************* + + Synopsis [Parses interfaces of the models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ) +{ + Ioa_ReadMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // parse the model + if ( !Ioa_ReadParseLineModel( pMod, pMod->pFirst ) ) + return 0; + // parse the inputs + Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) + if ( !Ioa_ReadParseLineInputs( pMod, pLine ) ) + return 0; + // parse the outputs + Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) + if ( !Ioa_ReadParseLineOutputs( pMod, pLine ) ) + return 0; + // parse the delay info + Vec_PtrForEachEntry( pMod->vDelays, pLine, k ) + if ( !Ioa_ReadParseLineDelay( pMod, pLine ) ) + return 0; + Vec_PtrForEachEntry( pMod->vArrivals, pLine, k ) + if ( !Ioa_ReadParseLineTimes( pMod, pLine, 0 ) ) + return 0; + Vec_PtrForEachEntry( pMod->vRequireds, pLine, k ) + if ( !Ioa_ReadParseLineTimes( pMod, pLine, 1 ) ) + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p ) +{ + Ntl_Man_t * pDesign; + Ioa_ReadMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // parse the latches + Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) + if ( !Ioa_ReadParseLineLatch( pMod, pLine ) ) + return NULL; + // parse the nodes + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Ioa_ReadParseLineNamesBlif( pMod, pLine ) ) + return NULL; + // parse the subcircuits + Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) + if ( !Ioa_ReadParseLineSubckt( pMod, pLine ) ) + return NULL; + // finalize the network + Ntl_ModelFixNonDrivenNets( pMod->pNtk ); + } + // return the network + pDesign = p->pDesign; + p->pDesign = NULL; + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineModel( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(vTokens) != 2 ) + { + sprintf( p->pMan->sError, "Line %d: The number of entries in .model line (%d) is different from two.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); + return 0; + } + p->pNtk = Ntl_ModelAlloc( p->pMan->pDesign, Vec_PtrEntry(vTokens, 1) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineInputs( Ioa_ReadMod_t * p, char * pLine ) +{ + Ntl_Net_t * pNet; + Ntl_Obj_t * pObj; + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + { + pObj = Ntl_ModelCreatePi( p->pNtk ); + pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); + if ( !Ntl_ModelSetNetDriver( pObj, pNet ) ) + { + sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNet->pName ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineOutputs( Ioa_ReadMod_t * p, char * pLine ) +{ + Ntl_Net_t * pNet; + Ntl_Obj_t * pObj; + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + { + pNet = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); + pObj = Ntl_ModelCreatePo( p->pNtk, pNet ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineLatch( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Ntl_Net_t * pNetLi, * pNetLo; + Ntl_Obj_t * pObj; + char * pToken, * pNameLi, * pNameLo; + int Init, Class; + Ioa_ReadSplitIntoTokens( 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.", Ioa_ReadGetLine(p->pMan, pToken) ); + return 0; + } + // create latch + pNameLi = Vec_PtrEntry( vTokens, 1 ); + pNameLo = Vec_PtrEntry( vTokens, 2 ); + pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLi ); + pNetLo = Ntl_ModelFindOrCreateNet( p->pNtk, pNameLo ); + pObj = Ntl_ModelCreateLatch( p->pNtk ); + pObj->pFanio[0] = pNetLi; + if ( !Ntl_ModelSetNetDriver( pObj, pNetLo ) ) + { + sprintf( p->pMan->sError, "Line %d: Net %s already has a driver.", Ioa_ReadGetLine(p->pMan, pToken), pNetLo->pName ); + return 0; + } + // get initial value + if ( Vec_PtrSize(vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); + return 0; + } + // get the register class + if ( Vec_PtrSize(vTokens) == 6 ) + Class = atoi( Vec_PtrEntry(vTokens,3) ); + else + Class = 0; + if ( Class < 0 || Class > (1<<24) ) + { + sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,4) ); + return 0; + } + pObj->LatchId = (Class << 2) | Init; + // get the clock + if ( Vec_PtrSize(vTokens) == 5 || Vec_PtrSize(vTokens) == 6 ) + { + pToken = Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-2); + pNetLi = Ntl_ModelFindOrCreateNet( p->pNtk, pToken ); + pObj->pFanio[1] = pNetLi; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineSubckt( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Ntl_Mod_t * pModel; + Ntl_Obj_t * pBox, * pTerm; + Ntl_Net_t * pNet; + char * pToken, * pName, ** ppNames; + int nEquals, i, k; + + // split the line into tokens + nEquals = Ioa_ReadCountChars( pLine, '=' ); + Ioa_ReadSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "subckt") ); + + // get the model for this box + pName = Vec_PtrEntry(vTokens,1); + pModel = Ntl_ManFindModel( p->pMan->pDesign, pName ); + if ( pModel == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Ioa_ReadGetLine(p->pMan, pToken), pName ); + return 0; + } + + // check if the number of tokens is correct + if ( nEquals != Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(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).", + Ioa_ReadGetLine(p->pMan, pToken), nEquals, Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) ); + return 0; + } + + // get the names + ppNames = (char **)Vec_PtrArray(vTokens) + 2; + + // create the box with these terminals + pBox = Ntl_ModelCreateBox( p->pNtk, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) ); + pBox->pImplem = pModel; + Ntl_ModelForEachPi( pModel, pTerm, i ) + { + // find this terminal among the formal inputs of the subcircuit + pName = Ntl_ObjFanout0(pTerm)->pName; + 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.", + Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName ); + return 0; + } + // create the BI with the actual name + pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + Ntl_ObjSetFanin( pBox, pNet, i ); + } + Ntl_ModelForEachPo( pModel, pTerm, i ) + { + // find this terminal among the formal outputs of the subcircuit + pName = Ntl_ObjFanin0(pTerm)->pName; + 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 model \"%s\" as a formal output of the subcircuit.", + Ioa_ReadGetLine(p->pMan, pToken), pName, pModel->pName ); + return 0; + } + // create the BI with the actual name + pNet = Ntl_ModelFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + Ntl_ObjSetFanout( pBox, pNet, i ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineDelay( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + int RetValue1, RetValue2, Number1, Number2, Temp; + char * pToken, * pTokenNum; + float Delay; + assert( sizeof(float) == sizeof(int) ); + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "delay") ); + if ( Vec_PtrSize(vTokens) < 2 && Vec_PtrSize(vTokens) > 4 ) + { + sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (1, 2, or 3).", Ioa_ReadGetLine(p->pMan, pToken) ); + return 0; + } + // find the delay number + pTokenNum = Vec_PtrEntryLast(vTokens); + Delay = atof( pTokenNum ); + if ( Delay == 0.0 && pTokenNum[0] != '0' ) + { + sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) ); + return 0; + } + // find the PI/PO numbers + RetValue1 = 0; Number1 = -1; + if ( Vec_PtrSize(vTokens) > 2 ) + { + RetValue1 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number1 ); + if ( RetValue1 == 0 ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); + return 0; + } + } + RetValue2 = 0; Number2 = -1; + if ( Vec_PtrSize(vTokens) > 3 ) + { + RetValue2 = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 2), &Number2 ); + if ( RetValue2 == 0 ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs/POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 2) ); + return 0; + } + } + if ( RetValue1 == RetValue2 && RetValue1 ) + { + sprintf( p->pMan->sError, "Line %d: Both signals \"%s\" and \"%s\" listed appear to be PIs or POs.", + Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1), Vec_PtrEntry(vTokens, 2) ); + return 0; + } + if ( RetValue2 < RetValue1 ) + { + Temp = RetValue2; RetValue2 = RetValue1; RetValue1 = Temp; + Temp = Number2; Number2 = Number1; Number1 = Temp; + } + assert( RetValue1 == 0 || RetValue1 == -1 ); + assert( RetValue2 == 0 || RetValue2 == 1 ); + // store the values + if ( p->pNtk->vDelays == NULL ) + p->pNtk->vDelays = Vec_IntAlloc( 100 ); + Vec_IntPush( p->pNtk->vDelays, Number1 ); + Vec_IntPush( p->pNtk->vDelays, Number2 ); + Vec_IntPush( p->pNtk->vDelays, Aig_Float2Int(Delay) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineTimes( Ioa_ReadMod_t * p, char * pLine, int fOutput ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + int RetValue, Number; + char * pToken, * pTokenNum; + float Delay; + assert( sizeof(float) == sizeof(int) ); + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + if ( fOutput ) + assert( !strcmp(pToken, "output_required") ); + else + assert( !strcmp(pToken, "input_arrival") ); + if ( Vec_PtrSize(vTokens) != 3 ) + { + sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (3).", Ioa_ReadGetLine(p->pMan, pToken) ); + return 0; + } + // find the delay number + pTokenNum = Vec_PtrEntryLast(vTokens); + if ( !strcmp( pTokenNum, "-inf" ) ) + Delay = -AIG_INFINITY; + else if ( !strcmp( pTokenNum, "inf" ) ) + Delay = AIG_INFINITY; + else + Delay = atof( pTokenNum ); + if ( Delay == 0.0 && pTokenNum[0] != '0' ) + { + sprintf( p->pMan->sError, "Line %d: Delay value (%s) appears to be invalid.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntryLast(vTokens) ); + return 0; + } + // find the PI/PO numbers + if ( fOutput ) + { + RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number ); + if ( RetValue == 0 ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among POs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); + return 0; + } + // store the values + if ( p->pNtk->vRequireds == NULL ) + p->pNtk->vRequireds = Vec_IntAlloc( 100 ); + Vec_IntPush( p->pNtk->vRequireds, Number ); + Vec_IntPush( p->pNtk->vRequireds, Aig_Float2Int(Delay) ); + } + else + { + RetValue = Ntl_ModelFindPioNumber( p->pNtk, Vec_PtrEntry(vTokens, 1), &Number ); + if ( RetValue == 0 ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find signal \"%s\" among PIs.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); + return 0; + } + // store the values + if ( p->pNtk->vArrivals == NULL ) + p->pNtk->vArrivals = Vec_IntAlloc( 100 ); + Vec_IntPush( p->pNtk->vArrivals, Number ); + Vec_IntPush( p->pNtk->vArrivals, Aig_Float2Int(Delay) ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Ioa_ReadParseTableBlif( Ioa_ReadMod_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 + Ioa_ReadSplitIntoTokens( vTokens, pTable, '.' ); + if ( Vec_PtrSize(vTokens) == 0 ) + return Ntl_ManStoreSop( p->pMan->pDesign, " 0\n" ); + 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\".", Ioa_ReadGetLine(p->pMan, pOutput), pOutput ); + return NULL; + } + return Ntl_ManStoreSop( p->pMan->pDesign, (pOutput[0] == '0') ? " 0\n" : " 1\n" ); + } + pProduct = Vec_PtrEntry( vTokens, 0 ); + if ( Vec_PtrSize(vTokens) % 2 == 1 ) + { + sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Ioa_ReadGetLine(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).", Ioa_ReadGetLine(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.", Ioa_ReadGetLine(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).", Ioa_ReadGetLine(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 Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Ntl_Obj_t * pNode; + Ntl_Net_t * pNetOut, * pNetIn; + char * pNameOut, * pNameIn; + int i; + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + // parse the mapped node +// if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) +// return Ioa_ReadParseLineGateBlif( p, vTokens ); + // parse the regular name line + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); + pNameOut = Vec_PtrEntryLast( vTokens ); +/* + if ( strcmp( pNameOut, "18434" ) == 0 ) + { + int x = 0; + } +*/ + pNetOut = Ntl_ModelFindOrCreateNet( p->pNtk, pNameOut ); + // create fanins + pNode = Ntl_ModelCreateNode( p->pNtk, Vec_PtrSize(vTokens) - 2 ); + for ( i = 0; i < Vec_PtrSize(vTokens) - 2; i++ ) + { + pNameIn = Vec_PtrEntry(vTokens, i+1); + pNetIn = Ntl_ModelFindOrCreateNet( p->pNtk, pNameIn ); + Ntl_ObjSetFanin( pNode, pNetIn, i ); + } + if ( !Ntl_ModelSetNetDriver( pNode, pNetOut ) ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Ioa_ReadGetLine(p->pMan, pNameOut), pNameOut ); + return 0; + } + // parse the table of this node + pNode->pSop = Ioa_ReadParseTableBlif( p, pNameOut + strlen(pNameOut), pNode->nFanins ); + if ( pNode->pSop == NULL ) + return 0; + pNode->pSop = Ntl_ManStoreSop( p->pNtk->pMan, pNode->pSop ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c new file mode 100644 index 00000000..b84ac1a5 --- /dev/null +++ b/src/aig/ntl/ntlTable.c @@ -0,0 +1,217 @@ +/**CFile**************************************************************** + + FileName [ntlTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Name table manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing for strings +static unsigned Ntl_HashString( 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 DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory for the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Net_t * Ntl_ModelCreateNet( Ntl_Mod_t * p, char * pName ) +{ + Ntl_Net_t * pNet; + pNet = (Ntl_Net_t *)Aig_MmFlexEntryFetch( p->pMan->pMemObjs, sizeof(Ntl_Net_t) + strlen(pName) + 1 ); + memset( pNet, 0, sizeof(Ntl_Net_t) ); + strcpy( pNet->pName, pName ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ModelTableResize( Ntl_Mod_t * p ) +{ + Ntl_Net_t ** pTableNew, ** ppSpot, * pEntry, * pEntry2; + int nTableSizeNew, Counter, e, clk; +clk = clock(); + // get the new table size + nTableSizeNew = Aig_PrimeCudd( 3 * p->nTableSize ); + // allocate a new array + pTableNew = ALLOC( Ntl_Net_t *, nTableSizeNew ); + memset( pTableNew, 0, sizeof(Ntl_Net_t *) * nTableSizeNew ); + // rehash entries + Counter = 0; + for ( e = 0; e < p->nTableSize; e++ ) + for ( pEntry = p->pTable[e], pEntry2 = pEntry? pEntry->pNext : NULL; + pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNext : NULL ) + { + ppSpot = pTableNew + Ntl_HashString( pEntry->pName, nTableSizeNew ); + pEntry->pNext = *ppSpot; + *ppSpot = pEntry; + Counter++; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", p->nTableSize, nTableSizeNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( p->pTable ); + p->pTable = pTableNew; + p->nTableSize = nTableSizeNew; +} + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName ) +{ + Ntl_Net_t * pEnt; + unsigned Key = Ntl_HashString( pName, p->nTableSize ); + for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext ) + if ( !strcmp( pEnt->pName, pName ) ) + return pEnt; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ntl_Net_t * Ntl_ModelFindOrCreateNet( Ntl_Mod_t * p, char * pName ) +{ + Ntl_Net_t * pEnt; + unsigned Key = Ntl_HashString( pName, p->nTableSize ); + for ( pEnt = p->pTable[Key]; pEnt; pEnt = pEnt->pNext ) + if ( !strcmp( pEnt->pName, pName ) ) + return pEnt; + pEnt = Ntl_ModelCreateNet( p, pName ); + pEnt->pNext = p->pTable[Key]; + p->pTable[Key] = pEnt; + if ( ++p->nEntries > 2 * p->nTableSize ) + Ntl_ModelTableResize( p ); + return pEnt; +} + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ) +{ + if ( pObj->pFanio[pObj->nFanins] != NULL ) + return 0; + if ( pNet->pDriver != NULL ) + return 0; + pObj->pFanio[pObj->nFanins] = pNet; + pNet->pDriver = pObj; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns -1, 0, +1 (when it is PI, not found, or PO).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber ) +{ + Ntl_Net_t * pNet; + Ntl_Obj_t * pObj; + int i; + *pNumber = -1; + pNet = Ntl_ModelFindNet( p, pName ); + if ( pNet == NULL ) + return 0; + Ntl_ModelForEachPo( p, pObj, i ) + { + if ( Ntl_ObjFanin0(pObj) == pNet ) + { + *pNumber = i; + return 1; + } + } + Ntl_ModelForEachPi( p, pObj, i ) + { + if ( Ntl_ObjFanout0(pObj) == pNet ) + { + *pNumber = i; + return -1; + } + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlTime.c b/src/aig/ntl/ntlTime.c new file mode 100644 index 00000000..50f3d290 --- /dev/null +++ b/src/aig/ntl/ntlTime.c @@ -0,0 +1,128 @@ +/**CFile**************************************************************** + + FileName [ntlTime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Creates timing manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlTime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Ntl_ManCreateDelayTable( Vec_Int_t * vDelays, int nIns, int nOuts ) +{ + float * pDelayTable, Delay; + int iIn, iOut, i, k; + assert( Vec_IntSize(vDelays) % 3 == 0 ); + pDelayTable = ALLOC( float, nIns * nOuts ); + memset( pDelayTable, 0, sizeof(float) * nIns * nOuts ); + Vec_IntForEachEntry( vDelays, iIn, i ) + { + iOut = Vec_IntEntry(vDelays, ++i); + Delay = Aig_Int2Float( Vec_IntEntry(vDelays, ++i) ); + if ( iIn == -1 && iOut == -1 ) + for ( k = 0; k < nIns * nOuts; k++ ) + pDelayTable[k] = Delay; + else if ( iIn == -1 ) + for ( k = 0; k < nIns; k++ ) + pDelayTable[iOut * nIns + k] = Delay; + else if ( iOut == -1 ) + for ( k = 0; k < nOuts; k++ ) + pDelayTable[k * nIns + iIn] = Delay; + else + pDelayTable[iOut * nIns + iIn] = Delay; + } + return pDelayTable; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ) +{ + Tim_Man_t * pMan; + Vec_Ptr_t * vDelayTables; + Ntl_Mod_t * pRoot, * pModel; + Ntl_Obj_t * pObj; + int i, curPi, iBox, Entry; + assert( p->pAig != NULL ); + pRoot = Vec_PtrEntry( p->vModels, 0 ); + // start the timing manager + pMan = Tim_ManStart( Aig_ManPiNum(p->pAig), Aig_ManPoNum(p->pAig) ); + // unpack the data in the arrival times + if ( pRoot->vArrivals ) + Vec_IntForEachEntry( pRoot->vArrivals, Entry, i ) + Tim_ManInitPiArrival( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vArrivals,++i)) ); + // unpack the data in the required times + if ( pRoot->vRequireds ) + Vec_IntForEachEntry( pRoot->vRequireds, Entry, i ) + Tim_ManInitPoRequired( pMan, Entry, Aig_Int2Float(Vec_IntEntry(pRoot->vRequireds,++i)) ); + // derive timing tables + vDelayTables = Vec_PtrAlloc( Vec_PtrSize(p->vModels) ); + Ntl_ManForEachModel( p, pModel, i ) + { + if ( pModel->vDelays ) + pModel->pDelayTable = Ntl_ManCreateDelayTable( pModel->vDelays, Ntl_ModelPiNum(pModel), Ntl_ModelPoNum(pModel) ); + Vec_PtrPush( vDelayTables, pModel->pDelayTable ); + } + Tim_ManSetDelayTables( pMan, vDelayTables ); + // set up the boxes + iBox = 0; + curPi = Ntl_ModelCiNum(pRoot); + Ntl_ManForEachBox( p, pObj, i ) + { + Tim_ManCreateBoxFirst( pMan, Vec_IntEntry(p->vBox1Cos, iBox), Ntl_ObjFaninNum(pObj), curPi, Ntl_ObjFanoutNum(pObj), pObj->pImplem->pDelayTable ); + curPi += Ntl_ObjFanoutNum(pObj); + iBox++; + } + // forget refs to the delay tables in the network + Ntl_ManForEachModel( p, pModel, i ) + pModel->pDelayTable = NULL; +// Tim_ManPrint( pMan ); + return pMan; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c new file mode 100644 index 00000000..8bcd2044 --- /dev/null +++ b/src/aig/ntl/ntlWriteBlif.c @@ -0,0 +1,127 @@ +/**CFile**************************************************************** + + FileName [ntlWriteBlif.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: ntlWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" +#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes one model into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel ) +{ + Ntl_Obj_t * pObj; + Ntl_Net_t * pNet; + int i, k; + fprintf( pFile, ".model %s\n", pModel->pName ); + fprintf( pFile, ".inputs" ); + Ntl_ModelForEachPi( pModel, pObj, i ) + fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs" ); + Ntl_ModelForEachPo( pModel, pObj, i ) + fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); + fprintf( pFile, "\n" ); + Ntl_ModelForEachObj( pModel, pObj, i ) + { + if ( Ntl_ObjIsNode(pObj) ) + { + fprintf( pFile, ".names" ); + Ntl_ObjForEachFanin( pObj, pNet, k ) + fprintf( pFile, " %s", pNet->pName ); + fprintf( pFile, " %s\n", Ntl_ObjFanout0(pObj)->pName ); + fprintf( pFile, "%s", pObj->pSop ); + } + else if ( Ntl_ObjIsLatch(pObj) ) + { + fprintf( pFile, ".latch" ); + fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); + fprintf( pFile, " %s", Ntl_ObjFanout0(pObj)->pName ); + if ( pObj->LatchId >> 2 ) + fprintf( pFile, " %d", pObj->LatchId >> 2 ); + if ( pObj->pFanio[1] != NULL ) + fprintf( pFile, " %s", Ntl_ObjFanin(pObj, 1)->pName ); + fprintf( pFile, " %d", pObj->LatchId & 3 ); + fprintf( pFile, "\n" ); + } + else if ( Ntl_ObjIsBox(pObj) ) + { + fprintf( pFile, ".subckt %s", pObj->pImplem->pName ); + Ntl_ObjForEachFanin( pObj, pNet, k ) + fprintf( pFile, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName ); + Ntl_ObjForEachFanout( pObj, pNet, k ) + fprintf( pFile, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName ); + fprintf( pFile, "\n" ); + } + } + fprintf( pFile, ".end\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the network into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Ntl_Mod_t * pModel; + int i; + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Ioa_TimeStamp() ); + // write the models + Ntl_ManForEachModel( p, pModel, i ) + Ioa_WriteBlifModel( pFile, pModel ); + // close the file + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntl_.c b/src/aig/ntl/ntl_.c new file mode 100644 index 00000000..4b3ad684 --- /dev/null +++ b/src/aig/ntl/ntl_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [ntl_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntl_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + |