From 661abab094143930f58633dfad415468a90cef6f Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 6 Apr 2008 08:01:00 -0700 Subject: Version abc80406 --- src/aig/ntl/module.make | 2 + src/aig/ntl/ntl.h | 12 ++- src/aig/ntl/ntlExtract.c | 209 ++++++++++++++++++++++++++++++++++++++++++++- src/aig/ntl/ntlFraig.c | 156 +++++++++++++++++++++++++++++++++ src/aig/ntl/ntlInsert.c | 118 +++++++++++++++++++++++++ src/aig/ntl/ntlMan.c | 3 + src/aig/ntl/ntlReadBlif.c | 9 ++ src/aig/ntl/ntlTable.c | 29 +++++++ src/aig/ntl/ntlUtil.c | 165 +++++++++++++++++++++++++++++++++++ src/aig/ntl/ntlWriteBlif.c | 46 ++++++++++ 10 files changed, 744 insertions(+), 5 deletions(-) create mode 100644 src/aig/ntl/ntlFraig.c create mode 100644 src/aig/ntl/ntlUtil.c (limited to 'src/aig/ntl') diff --git a/src/aig/ntl/module.make b/src/aig/ntl/module.make index aba4fbf2..d3f2cfdd 100644 --- a/src/aig/ntl/module.make +++ b/src/aig/ntl/module.make @@ -1,6 +1,7 @@ SRC += src/aig/ntl/ntlCheck.c \ src/aig/ntl/ntlCore.c \ src/aig/ntl/ntlExtract.c \ + src/aig/ntl/ntlFraig.c \ src/aig/ntl/ntlInsert.c \ src/aig/ntl/ntlMan.c \ src/aig/ntl/ntlMap.c \ @@ -8,5 +9,6 @@ SRC += src/aig/ntl/ntlCheck.c \ src/aig/ntl/ntlReadBlif.c \ src/aig/ntl/ntlTable.c \ src/aig/ntl/ntlTime.c \ + src/aig/ntl/ntlUtil.c \ src/aig/ntl/ntlWriteBlif.c diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h index 6d4f5c29..2e109f05 100644 --- a/src/aig/ntl/ntl.h +++ b/src/aig/ntl/ntl.h @@ -103,9 +103,8 @@ struct Ntl_Obj_t_ Ntl_Mod_t * pModel; // the model void * pCopy; // the copy of this object unsigned Type : 3; // object type - unsigned Id : 27; // object ID - unsigned MarkA : 1; // temporary mark - unsigned MarkB : 1; // temporary mark + unsigned fMark : 1; // temporary mark + unsigned Id : 28; // object ID int nFanins; // the number of fanins int nFanouts; // the number of fanouts union { // functionality @@ -123,6 +122,7 @@ struct Ntl_Net_t_ Ntl_Obj_t * pDriver; // driver of the net char nVisits; // the number of times the net is visited char fMark; // temporary mark + char fCompl; // complemented attribue char pName[0]; // the name of this net }; @@ -234,6 +234,7 @@ extern Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p ); extern char * Ntl_SopFromTruth( Ntl_Man_t * p, unsigned * pTruth, int nVars, Vec_Int_t * vCover ); /*=== ntlInsert.c ==========================================================*/ extern int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ); +extern int Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); extern int Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ); /*=== ntlCheck.c ==========================================================*/ extern int Ntl_ManCheck( Ntl_Man_t * pMan ); @@ -270,12 +271,17 @@ 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_ModelFindPioNumber( Ntl_Mod_t * p, char * pName, int * pNumber ); extern int Ntl_ModelSetNetDriver( Ntl_Obj_t * pObj, Ntl_Net_t * pNet ); +extern void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ); /*=== 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 ); +/*=== ntlUtil.c ==========================================================*/ +extern int Ntl_ManTransformCoDrivers( Ntl_Man_t * p ); +extern Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ); +extern Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ); #ifdef __cplusplus } diff --git a/src/aig/ntl/ntlExtract.c b/src/aig/ntl/ntlExtract.c index cd21c95f..848f113a 100644 --- a/src/aig/ntl/ntlExtract.c +++ b/src/aig/ntl/ntlExtract.c @@ -211,6 +211,41 @@ char * Ntl_SopCreateFromIsop( Aig_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover return pSop; } +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_SopToIsop( char * pSop, Vec_Int_t * vCover ) +{ + char * pCube; + int k, nVars, Entry; + nVars = Ntl_SopGetVarNum( pSop ); + assert( nVars > 0 ); + // create cubes + Vec_IntClear( vCover ); + for ( pCube = pSop; *pCube; pCube += nVars + 3 ) + { + Entry = 0; + for ( k = nVars - 1; k >= 0; k-- ) + if ( pCube[k] == '0' ) + Entry = (Entry << 2) | 1; + else if ( pCube[k] == '1' ) + Entry = (Entry << 2) | 2; + else if ( pCube[k] == '-' ) + Entry = (Entry << 2); + else + assert( 0 ); + Vec_IntPush( vCover, Entry ); + } +} + /**Function************************************************************* Synopsis [Transforms truth table into the SOP.] @@ -404,10 +439,11 @@ int Ntl_ManExtract_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ) } //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->pCopy = Ntl_ManBuildNodeAig( pObj ); + if ( pNet->fCompl ) + pNet->pCopy = Aig_Not(pNet->pCopy); pNet->nVisits = 2; return 1; } @@ -602,9 +638,10 @@ int Ntl_ManCollapse_rec( Ntl_Man_t * p, Ntl_Net_t * pNet ) if ( !Ntl_ManBuildModelAig( p, pObj ) ) return 0; } - // store the node if ( Ntl_ObjIsNode(pObj) ) pNet->pCopy = Ntl_ManBuildNodeAig( pObj ); + if ( pNet->fCompl ) + pNet->pCopy = Aig_Not(pNet->pCopy); pNet->nVisits = 2; return 1; } @@ -692,6 +729,174 @@ Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p ) return pAig; } +/**Function************************************************************* + + Synopsis [Increments reference counter of the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ntl_NetIncrementRefs( Ntl_Net_t * pNet ) +{ + int nRefs = (int)pNet->pCopy; + pNet->pCopy = (void *)(nRefs + 1); +} + +/**Function************************************************************* + + Synopsis [Extracts logic newtork out of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Obj_t * Ntl_ManExtractNwk_rec( Ntl_Man_t * p, Ntl_Net_t * pNet, Nwk_Man_t * pNtk, Vec_Int_t * vCover, Vec_Int_t * vMemory ) +{ + extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); + Ntl_Net_t * pFaninNet; + Nwk_Obj_t * pNode; + int i; + if ( pNet->fMark ) + return pNet->pCopy; + pNet->fMark = 1; + pNode = Nwk_ManCreateNode( pNtk, Ntl_ObjFaninNum(pNet->pDriver), (int)pNet->pCopy ); + Ntl_ObjForEachFanin( pNet->pDriver, pFaninNet, i ) + { + Ntl_ManExtractNwk_rec( p, pFaninNet, pNtk, vCover, vMemory ); + Nwk_ObjAddFanin( pNode, pFaninNet->pCopy ); + } + if ( Ntl_ObjFaninNum(pNet->pDriver) == 0 ) + pNode->pFunc = Hop_NotCond( Hop_ManConst1(pNtk->pManHop), Ntl_SopIsConst0(pNet->pDriver->pSop) ); + else + { + Ntl_SopToIsop( pNet->pDriver->pSop, vCover ); + pNode->pFunc = Kit_CoverToHop( pNtk->pManHop, vCover, Ntl_ObjFaninNum(pNet->pDriver), vMemory ); + } + return pNet->pCopy = pNode; +} + +/**Function************************************************************* + + Synopsis [Extracts logic newtork out of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Ntl_ManExtractNwk( Ntl_Man_t * p, Aig_Man_t * pAig ) +{ + Nwk_Man_t * pNtk; + Nwk_Obj_t * pNode; + Ntl_Mod_t * pRoot; + Ntl_Net_t * pNet; + Ntl_Obj_t * pObj; + Aig_Obj_t * pAnd; + Vec_Int_t * vCover, * vMemory; + int i, k; + pRoot = Ntl_ManRootModel( p ); + assert( Ntl_ModelBoxNum(pRoot) == 0 ); + assert( Ntl_ModelLatchNum(pRoot) == 0 ); + assert( Ntl_ModelPiNum(pRoot) == Aig_ManPiNum(pAig) ); + assert( Ntl_ModelPoNum(pRoot) == Aig_ManPoNum(pAig) ); + vCover = Vec_IntAlloc( 100 ); + vMemory = Vec_IntAlloc( 1 << 16 ); + // count the number of fanouts of each net + Ntl_ModelForEachNet( pRoot, pNet, i ) + { + pNet->pCopy = NULL; + pNet->fMark = 0; + } + Ntl_ModelForEachObj( pRoot, pObj, i ) + Ntl_ObjForEachFanin( pObj, pNet, k ) + Ntl_NetIncrementRefs( pNet ); + // construct the network + pNtk = Nwk_ManAlloc(); + pNtk->pName = Aig_UtilStrsav( pAig->pName ); + pNtk->pSpec = Aig_UtilStrsav( pAig->pSpec ); + Aig_ManSetPioNumbers( pAig ); + Aig_ManForEachObj( pAig, pAnd, i ) + { + if ( Aig_ObjIsPi(pAnd) ) + { + pObj = Ntl_ModelPi( pRoot, Aig_ObjPioNum(pAnd) ); + pNet = Ntl_ObjFanout0(pObj); + pNet->fMark = 1; + pNet->pCopy = Nwk_ManCreateCi( pNtk, (int)pNet->pCopy ); + } + else if ( Aig_ObjIsPo(pAnd) ) + { + pObj = Ntl_ModelPo( pRoot, Aig_ObjPioNum(pAnd) ); + pNet = Ntl_ObjFanin0(pObj); + pNet->pCopy = Ntl_ManExtractNwk_rec( p, pNet, pNtk, vCover, vMemory ); + pNode = Nwk_ManCreateCo( pNtk ); + pNode->fCompl = pNet->fCompl; + Nwk_ObjAddFanin( pNode, pNet->pCopy ); + } + } + Aig_ManCleanPioNumbers( pAig ); + Ntl_ModelForEachNet( pRoot, pNet, i ) + { + pNet->pCopy = NULL; + pNet->fMark = 0; + } + Vec_IntFree( vCover ); + Vec_IntFree( vMemory ); + // create timing manager from the current design + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Extracts logic newtork out of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nwk_Man_t * Ntl_ManReadNwk( char * pFileName, Aig_Man_t * pAig, Tim_Man_t * pManTime ) +{ + Nwk_Man_t * pNtk; + Ntl_Man_t * pNtl; + Ntl_Mod_t * pRoot; + pNtl = Ioa_ReadBlif( pFileName, 1 ); + if ( pNtl == NULL ) + { + printf( "Ntl_ManReadNwk(): Reading BLIF has failed.\n" ); + return NULL; + } + pRoot = Ntl_ManRootModel( pNtl ); + if ( Ntl_ModelPiNum(pRoot) != Aig_ManPiNum(pAig) ) + { + printf( "Ntl_ManReadNwk(): The number of primary inputs does not match (%d and %d).\n", + Ntl_ModelPiNum(pRoot), Aig_ManPiNum(pAig) ); + return NULL; + } + if ( Ntl_ModelPoNum(pRoot) != Aig_ManPoNum(pAig) ) + { + printf( "Ntl_ManReadNwk(): The number of primary outputs does not match (%d and %d).\n", + Ntl_ModelPoNum(pRoot), Aig_ManPoNum(pAig) ); + return NULL; + } + pNtk = Ntl_ManExtractNwk( pNtl, pAig ); + Ntl_ManFree( pNtl ); + if ( pManTime ) + pNtk->pManTime = Tim_ManDup( pManTime, 0 ); + return pNtk; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/ntl/ntlFraig.c b/src/aig/ntl/ntlFraig.c new file mode 100644 index 00000000..7153f081 --- /dev/null +++ b/src/aig/ntl/ntlFraig.c @@ -0,0 +1,156 @@ +/**CFile**************************************************************** + + FileName [ntlFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Performing fraiging with white-boxes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns AIG with WB after fraiging.] + + Description [pAig points to the nodes of pNew derived using it. + pNew points to the nodes of pAigCol derived using it.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t ** Ntl_ManFraigDeriveClasses( Aig_Man_t * pAig, Ntl_Man_t * pNew, Aig_Man_t * pAigCol ) +{ + Ntl_Net_t * pNet; + Aig_Obj_t ** pReprs = NULL, ** pMapBack = NULL; + Aig_Obj_t * pObj, * pObjCol, * pObjColRepr, * pCorresp; + int i; + + // map the AIG managers + Aig_ManForEachObj( pAig, pObj, i ) + if ( Aig_ObjIsConst1(pObj) ) + pObj->pData = Aig_ManConst1(pAigCol); + else if ( !Aig_ObjIsPo(pObj) ) + { + pNet = pObj->pData; + pObjCol = Aig_Regular(pNet->pCopy); + pObj->pData = pObjCol; + } + + // create mapping from the collapsed manager into the original manager + pMapBack = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAigCol) ); + memset( pMapBack, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAigCol) ); + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + continue; + pObjCol = pObj->pData; + if ( pMapBack[pObjCol->Id] == NULL ) + pMapBack[pObjCol->Id] = pObj; + } + + // create the equivalence classes for the original manager + pReprs = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + memset( pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + continue; + // get the collapsed node + pObjCol = pObj->pData; + // get the representative of the collapsed node + pObjColRepr = pAigCol->pReprs[pObjCol->Id]; + if ( pObjColRepr == NULL ) + pObjColRepr = pObjCol; + // get the corresponding original node + pCorresp = pMapBack[pObjColRepr->Id]; + if ( pCorresp == NULL || pCorresp == pObj ) + continue; + // set the representative + if ( pCorresp->Id < pObj->Id ) + pReprs[pObj->Id] = pCorresp; + else + pReprs[pCorresp->Id] = pObj; + } + free( pMapBack ); + return pReprs; +} + +/**Function************************************************************* + + Synopsis [Returns AIG with WB after fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ntl_ManFraig( Ntl_Man_t * p, Aig_Man_t * pAig, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose ) +{ + Ntl_Man_t * pNew; + Aig_Man_t * pAigCol, * pTemp; + assert( pAig->pReprs == NULL ); + + // create a new netlist whose nodes are in 1-to-1 relationship with AIG + pNew = Ntl_ManDup( p ); + if ( !Ntl_ManInsertAig( pNew, pAig ) ) + { + Ntl_ManFree( pNew ); + printf( "Ntk_ManFraig(): Inserting AIG has failed.\n" ); + return NULL; + } + + // collapse the AIG + pAigCol = Ntl_ManCollapse( pNew ); + // perform fraiging for the given design + if ( nPartSize == 0 ) + nPartSize = Aig_ManPoNum(pAigCol); + pTemp = Aig_ManFraigPartitioned( pAigCol, nPartSize, nConfLimit, nLevelMax, fVerbose ); + Aig_ManStop( pTemp ); + + // transfer equivalence classes to the original AIG + pAig->pReprs = Ntl_ManFraigDeriveClasses( pAig, pNew, pAigCol ); + pAig->nReprsAlloc = Aig_ManObjNumMax(pAig); + // cleanup + Aig_ManStop( pAigCol ); + Ntl_ManFree( pNew ); + + // derive the new AIG + pTemp = Aig_ManDupRepresDfs( pAig ); + // duplicate the timing manager + if ( pAig->pManTime ) + pTemp->pManTime = Tim_ManDup( pAig->pManTime, 0 ); + // reset levels + Aig_ManChoiceLevel( pTemp ); + return pTemp; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlInsert.c b/src/aig/ntl/ntlInsert.c index f02b4716..10b83660 100644 --- a/src/aig/ntl/ntlInsert.c +++ b/src/aig/ntl/ntlInsert.c @@ -59,6 +59,7 @@ int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ) pRoot = Ntl_ManRootModel( p ); Ntl_ModelForEachNode( pRoot, pNode, i ) Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL ); + pRoot->nObjs[NTL_OBJ_NODE] = 0; // start mapping of AIG nodes into their copies vCopies = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); Ntl_ManForEachCiNet( p, pNet, i ) @@ -123,6 +124,122 @@ int Ntl_ManInsert( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ) return 1; } +/**Function************************************************************* + + Synopsis [Inserts the given mapping into the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ) +{ + char Buffer[100]; + Ntl_Mod_t * pRoot; + Ntl_Obj_t * pNode; + Ntl_Net_t * pNet, * pNetCo; + Aig_Obj_t * pObj, * pFanin; + int i, nDigits, Counter; + assert( Vec_PtrSize(p->vCis) == Aig_ManPiNum(pAig) ); + assert( Vec_PtrSize(p->vCos) == Aig_ManPoNum(pAig) ); + // set the correspondence between the PI/PO nodes + Aig_ManCleanData( pAig ); + Ntl_ManForEachCiNet( p, pNet, i ) + Aig_ManPi( pAig, i )->pData = pNet; +// Ntl_ManForEachCoNet( p, pNet, i ) +// Nwk_ManCo( pNtk, i )->pCopy = pNet; + // remove old nodes + pRoot = Ntl_ManRootModel( p ); + Ntl_ModelForEachNode( pRoot, pNode, i ) + Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL ); + pRoot->nObjs[NTL_OBJ_NODE] = 0; + // create constant node if needed + if ( Aig_ManConst1(pAig)->nRefs > 0 ) + { + pNode = Ntl_ModelCreateNode( pRoot, 0 ); + pNode->pSop = Ntl_ManStoreSop( p, " 1\n" ); + if ( (pNet = Ntl_ModelFindNet( pRoot, "Const1" )) ) + { + printf( "Ntl_ManInsertAig(): Internal error: Intermediate net name is not unique.\n" ); + return 0; + } + pNet = Ntl_ModelFindOrCreateNet( pRoot, "Const1" ); + if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) + { + printf( "Ntl_ManInsertAig(): Internal error: Net has more than one fanin.\n" ); + return 0; + } + Aig_ManConst1(pAig)->pData = pNet; + } + // create a new node for each LUT + Counter = 0; + nDigits = Aig_Base10Log( Aig_ManNodeNum(pAig) ); + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjFanin0(pObj)->pData == NULL || Aig_ObjFanin1(pObj)->pData == NULL ) + { + printf( "Ntl_ManInsertAig(): Internal error: Net not found.\n" ); + return 0; + } + pNode = Ntl_ModelCreateNode( pRoot, 2 ); + Ntl_ObjSetFanin( pNode, Aig_ObjFanin0(pObj)->pData, 0 ); + Ntl_ObjSetFanin( pNode, Aig_ObjFanin1(pObj)->pData, 1 ); + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pNode->pSop = Ntl_ManStoreSop( p, "00 1\n" ); + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + pNode->pSop = Ntl_ManStoreSop( p, "01 1\n" ); + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pNode->pSop = Ntl_ManStoreSop( p, "10 1\n" ); + else // if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pNode->pSop = Ntl_ManStoreSop( p, "11 1\n" ); + sprintf( Buffer, "and%0*d", nDigits, Counter++ ); + if ( (pNet = Ntl_ModelFindNet( pRoot, Buffer )) ) + { + printf( "Ntl_ManInsertAig(): Internal error: Intermediate net name is not unique.\n" ); + return 0; + } + pNet = Ntl_ModelFindOrCreateNet( pRoot, Buffer ); + if ( !Ntl_ModelSetNetDriver( pNode, pNet ) ) + { + printf( "Ntl_ManInsertAig(): Internal error: Net has more than one fanin.\n" ); + return 0; + } + pObj->pData = pNet; + } + // 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; + // get the corresponding PO and its driver + pObj = Aig_ManPo( pAig, i ); + pFanin = Aig_ObjFanin0( pObj ); + // get the net driving the driver + pNet = pFanin->pData; + pNode = Ntl_ModelCreateNode( pRoot, 1 ); + pNode->pSop = Aig_ObjFaninC0(pObj)? 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; + } + } + return 1; +} + + /**Function************************************************************* Synopsis [Inserts the given mapping into the netlist.] @@ -157,6 +274,7 @@ int Ntl_ManInsertNtk( Ntl_Man_t * p, Nwk_Man_t * pNtk ) pRoot = Ntl_ManRootModel( p ); Ntl_ModelForEachNode( pRoot, pNode, i ) Vec_PtrWriteEntry( pRoot->vObjs, pNode->Id, NULL ); + pRoot->nObjs[NTL_OBJ_NODE] = 0; // create a new node for each LUT vTruth = Vec_IntAlloc( 1 << 16 ); vCover = Vec_IntAlloc( 1 << 16 ); diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c index 82660263..83219df7 100644 --- a/src/aig/ntl/ntlMan.c +++ b/src/aig/ntl/ntlMan.c @@ -267,6 +267,9 @@ Ntl_Mod_t * Ntl_ModelDup( Ntl_Man_t * pManNew, Ntl_Mod_t * pModelOld ) if ( Ntl_ObjIsNode(pObj) ) ((Ntl_Obj_t *)pObj->pCopy)->pSop = Ntl_ManStoreSop( pManNew, pObj->pSop ); } + pModelNew->vDelays = pModelOld->vDelays? Vec_IntDup( pModelOld->vDelays ) : NULL; + pModelNew->vArrivals = pModelOld->vArrivals? Vec_IntDup( pModelOld->vArrivals ) : NULL; + pModelNew->vRequireds = pModelOld->vRequireds? Vec_IntDup( pModelOld->vRequireds ) : NULL; return pModelNew; } diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c index 2cf3caaa..ce3a2051 100644 --- a/src/aig/ntl/ntlReadBlif.c +++ b/src/aig/ntl/ntlReadBlif.c @@ -109,6 +109,7 @@ Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) FILE * pFile; Ioa_ReadMan_t * p; Ntl_Man_t * pDesign; + int nNodes; // check that the file is available pFile = fopen( pFileName, "rb" ); @@ -164,6 +165,9 @@ Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) } } + // transform the design by removing the CO drivers + if ( (nNodes = Ntl_ManTransformCoDrivers(pDesign)) ) + printf( "The design was transformed by removing %d buf/inv CO drivers.\n", nNodes ); //Ioa_WriteBlif( pDesign, "_temp_.blif" ); return pDesign; } @@ -614,6 +618,11 @@ static Ntl_Man_t * Ioa_ReadParse( Ioa_ReadMan_t * p ) // finalize the network Ntl_ModelFixNonDrivenNets( pMod->pNtk ); } + if ( i == 0 ) + return NULL; + // update the design name + pMod = Vec_PtrEntry( p->vModels, 0 ); + p->pDesign->pName = Ntl_ManStoreName( p->pDesign, pMod->pNtk->pName ); // return the network pDesign = p->pDesign; p->pDesign = NULL; diff --git a/src/aig/ntl/ntlTable.c b/src/aig/ntl/ntlTable.c index 909a64fd..df982481 100644 --- a/src/aig/ntl/ntlTable.c +++ b/src/aig/ntl/ntlTable.c @@ -123,6 +123,35 @@ Ntl_Net_t * Ntl_ModelFindNet( Ntl_Mod_t * p, char * pName ) return NULL; } +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntl_ModelDeleteNet( Ntl_Mod_t * p, Ntl_Net_t * pNet ) +{ + Ntl_Net_t * pEnt, * pPrev; + unsigned Key = Ntl_HashString( pNet->pName, p->nTableSize ); + for ( pPrev = NULL, pEnt = p->pTable[Key]; pEnt; pPrev = pEnt, pEnt = pEnt->pNext ) + if ( pEnt == pNet ) + break; + if ( pEnt == NULL ) + { + printf( "Ntl_ModelDeleteNet(): Net to be deleted is not found in the hash table.\n" ); + return; + } + if ( pPrev == NULL ) + p->pTable[Key] = pEnt->pNext; + else + pPrev->pNext = pEnt->pNext; +} + /**Function************************************************************* Synopsis [Finds or creates the net.] diff --git a/src/aig/ntl/ntlUtil.c b/src/aig/ntl/ntlUtil.c new file mode 100644 index 00000000..b13dd3a7 --- /dev/null +++ b/src/aig/ntl/ntlUtil.c @@ -0,0 +1,165 @@ +/**CFile**************************************************************** + + FileName [ntlUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Netlist representation.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ntlUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ntl.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if netlist was written by ABC with added bufs/invs.] + + Description [Should be called immediately after reading from file.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ntl_ManTransformCoDrivers( Ntl_Man_t * p ) +{ + Vec_Ptr_t * vCoNets; + Ntl_Net_t * pNetCo, * pNetFanin; + Ntl_Obj_t * pObj; + Ntl_Mod_t * pRoot; + int i, k, Counter; + pRoot = Ntl_ManRootModel( p ); + // collect the nets of the root model + vCoNets = Vec_PtrAlloc( 1000 ); + Ntl_ModelForEachPo( pRoot, pObj, i ) + if ( !Ntl_ObjFanin0(pObj)->fMark ) + { + Ntl_ObjFanin0(pObj)->fMark = 1; + Vec_PtrPush( vCoNets, Ntl_ObjFanin0(pObj) ); + } + Ntl_ModelForEachLatch( pRoot, pObj, i ) + if ( !Ntl_ObjFanin0(pObj)->fMark ) + { + Ntl_ObjFanin0(pObj)->fMark = 1; + Vec_PtrPush( vCoNets, Ntl_ObjFanin0(pObj) ); + } + Ntl_ModelForEachBox( pRoot, pObj, k ) + Ntl_ObjForEachFanin( pObj, pNetCo, i ) + if ( !pNetCo->fMark ) + { + pNetCo->fMark = 1; + Vec_PtrPush( vCoNets, pNetCo ); + } + // check the nets + Vec_PtrForEachEntry( vCoNets, pNetCo, i ) + { + if ( !Ntl_ObjIsNode(pNetCo->pDriver) ) + continue; + if ( Ntl_ObjFaninNum(pNetCo->pDriver) != 1 ) + break; + pNetFanin = Ntl_ObjFanin0(pNetCo->pDriver); + if ( !Ntl_ObjIsNode(pNetFanin->pDriver) ) + break; + } + if ( i < Vec_PtrSize(vCoNets) ) + { + Vec_PtrFree( vCoNets ); + return 0; + } + + + // remove the buffers/inverters + Counter = 0; + Vec_PtrForEachEntry( vCoNets, pNetCo, i ) + { + pNetCo->fMark = 0; + if ( !Ntl_ObjIsNode(pNetCo->pDriver) ) + continue; + // if this net is driven by an interver + // set the complemented attribute of the CO + assert( Ntl_ObjFaninNum(pNetCo->pDriver) == 1 ); + pNetCo->fCompl = (int)(pNetCo->pDriver->pSop[0] == '0'); + // remove the driver + Vec_PtrWriteEntry( pRoot->vObjs, pNetCo->pDriver->Id, NULL ); + // remove the net + pNetFanin = Ntl_ObjFanin0(pNetCo->pDriver); + Ntl_ModelDeleteNet( pRoot, pNetFanin ); + // make the CO net point to the new driver + assert( Ntl_ObjIsNode(pNetFanin->pDriver) ); + pNetCo->pDriver = NULL; + pNetFanin->pDriver->pFanio[pNetFanin->pDriver->nFanins] = NULL; + Ntl_ModelSetNetDriver( pNetFanin->pDriver, pNetCo ); + Counter++; + } + Vec_PtrFree( vCoNets ); + pRoot->nObjs[NTL_OBJ_NODE] -= Counter; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Derives the array of CI names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_ManCollectCiNames( Ntl_Man_t * p ) +{ + Vec_Ptr_t * vNames; + Ntl_Net_t * pNet; + int i; + vNames = Vec_PtrAlloc( 1000 ); + Ntl_ManForEachCiNet( p, pNet, i ) + Vec_PtrPush( vNames, pNet->pName ); + return vNames; +} + +/**Function************************************************************* + + Synopsis [Derives the array of CI names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ntl_ManCollectCoNames( Ntl_Man_t * p ) +{ + Vec_Ptr_t * vNames; + Ntl_Net_t * pNet; + int i; + vNames = Vec_PtrAlloc( 1000 ); + Ntl_ManForEachCoNet( p, pNet, i ) + Vec_PtrPush( vNames, pNet->pName ); + return vNames; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c index 8bcd2044..fddd4167 100644 --- a/src/aig/ntl/ntlWriteBlif.c +++ b/src/aig/ntl/ntlWriteBlif.c @@ -44,6 +44,7 @@ void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel ) { Ntl_Obj_t * pObj; Ntl_Net_t * pNet; + float Delay; int i, k; fprintf( pFile, ".model %s\n", pModel->pName ); fprintf( pFile, ".inputs" ); @@ -54,6 +55,51 @@ void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel ) Ntl_ModelForEachPo( pModel, pObj, i ) fprintf( pFile, " %s", Ntl_ObjFanin0(pObj)->pName ); fprintf( pFile, "\n" ); + // write delays + if ( pModel->vDelays ) + { + for ( i = 0; i < Vec_IntSize(pModel->vDelays); i += 3 ) + { + fprintf( pFile, ".delay" ); + fprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vDelays,i)))->pName ); + fprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vDelays,i+1)))->pName ); + fprintf( pFile, " %.3f", Aig_Int2Float(Vec_IntEntry(pModel->vDelays,i+2)) ); + fprintf( pFile, "\n" ); + } + } + if ( pModel->vArrivals ) + { + for ( i = 0; i < Vec_IntSize(pModel->vArrivals); i += 2 ) + { + fprintf( pFile, ".input_arrival" ); + fprintf( pFile, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vArrivals,i)))->pName ); + Delay = Aig_Int2Float(Vec_IntEntry(pModel->vArrivals,i+1)); + if ( Delay == -TIM_ETERNITY ) + fprintf( pFile, " -inf" ); + else if ( Delay == TIM_ETERNITY ) + fprintf( pFile, " inf" ); + else + fprintf( pFile, " %.3f", Delay ); + fprintf( pFile, "\n" ); + } + } + if ( pModel->vRequireds ) + { + for ( i = 0; i < Vec_IntSize(pModel->vRequireds); i += 2 ) + { + fprintf( pFile, ".output_required" ); + fprintf( pFile, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vRequireds,i)))->pName ); + Delay = Aig_Int2Float(Vec_IntEntry(pModel->vRequireds,i+1)); + if ( Delay == -TIM_ETERNITY ) + fprintf( pFile, " -inf" ); + else if ( Delay == TIM_ETERNITY ) + fprintf( pFile, " inf" ); + else + fprintf( pFile, " %.3f", Delay ); + fprintf( pFile, "\n" ); + } + } + // write objects Ntl_ModelForEachObj( pModel, pObj, i ) { if ( Ntl_ObjIsNode(pObj) ) -- cgit v1.2.3