diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2008-07-01 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2008-07-01 08:01:00 -0700 |
commit | 4a9789e58d27ecaba541ba3fcb0565a334dcd54b (patch) | |
tree | 1784dcf05dd78b0acddb7d52764f1e3fd6ef2d49 /src/aig | |
parent | d0341836ddb38ccc087bdac3df4e8b2ff7fe7a8f (diff) | |
download | abc-4a9789e58d27ecaba541ba3fcb0565a334dcd54b.tar.gz abc-4a9789e58d27ecaba541ba3fcb0565a334dcd54b.tar.bz2 abc-4a9789e58d27ecaba541ba3fcb0565a334dcd54b.zip |
Version abc80701
Diffstat (limited to 'src/aig')
-rw-r--r-- | src/aig/aig/aigPartReg.c | 4 | ||||
-rw-r--r-- | src/aig/dar/darCut.c | 2 | ||||
-rw-r--r-- | src/aig/fra/fra.h | 1 | ||||
-rw-r--r-- | src/aig/fra/fraInd.c | 57 | ||||
-rw-r--r-- | src/aig/fra/fraLcr.c | 2 | ||||
-rw-r--r-- | src/aig/ntl/ntl.h | 11 | ||||
-rw-r--r-- | src/aig/ntl/ntlExtract.c | 5 | ||||
-rw-r--r-- | src/aig/ntl/ntlFraig.c | 11 | ||||
-rw-r--r-- | src/aig/ntl/ntlMan.c | 9 | ||||
-rw-r--r-- | src/aig/ntl/ntlReadBlif.c | 135 | ||||
-rw-r--r-- | src/aig/ntl/ntlReadBlif_old.c | 1261 | ||||
-rw-r--r-- | src/aig/ntl/ntlTime.c | 3 | ||||
-rw-r--r-- | src/aig/ntl/ntlUtil.c | 13 | ||||
-rw-r--r-- | src/aig/ntl/ntlWriteBlif.c | 267 |
14 files changed, 1753 insertions, 28 deletions
diff --git a/src/aig/aig/aigPartReg.c b/src/aig/aig/aigPartReg.c index 145d2029..96ad1812 100644 --- a/src/aig/aig/aigPartReg.c +++ b/src/aig/aig/aigPartReg.c @@ -482,8 +482,8 @@ Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOve for ( Counter = 0; Counter < Aig_ManRegNum(pAig); Counter -= nOverSize ) { vPart = Vec_IntAlloc( nPartSize ); - for ( i = 0; i < nPartSize; i++ ) - if ( ++Counter < Aig_ManRegNum(pAig) ) + for ( i = 0; i < nPartSize; i++, Counter++ ) + if ( Counter < Aig_ManRegNum(pAig) ) Vec_IntPush( vPart, Counter ); if ( Vec_IntSize(vPart) <= nOverSize ) Vec_IntFree(vPart); diff --git a/src/aig/dar/darCut.c b/src/aig/dar/darCut.c index 79e4dcc4..6ebfec9d 100644 --- a/src/aig/dar/darCut.c +++ b/src/aig/dar/darCut.c @@ -586,7 +586,7 @@ Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) // create the cutset of the node pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); Dar_ObjSetCuts( pObj, pCutSet ); - Dar_ObjForEachCut( pObj, pCut, i ) + Dar_ObjForEachCutAll( pObj, pCut, i ) pCut->fUsed = 0; // add unit cut if needed pCut = pCutSet; diff --git a/src/aig/fra/fra.h b/src/aig/fra/fra.h index 025ce046..e9e7ad9c 100644 --- a/src/aig/fra/fra.h +++ b/src/aig/fra/fra.h @@ -97,6 +97,7 @@ struct Fra_Ssw_t_ int nFramesK; // number of frames for induction (1=simple) int nMaxImps; // max implications to consider int nMaxLevs; // max levels to consider + int nMinDomSize; // min clock domain considered for optimization int fUseImps; // use implications int fRewrite; // enable rewriting of the specualatively reduced model int fFraiging; // enable comb SAT sweeping as preprocessing diff --git a/src/aig/fra/fraInd.c b/src/aig/fra/fraInd.c index 9c52d0e2..89c4c677 100644 --- a/src/aig/fra/fraInd.c +++ b/src/aig/fra/fraInd.c @@ -235,6 +235,43 @@ void Fra_FramesAddMore( Aig_Man_t * p, int nFrames ) /**Function************************************************************* + Synopsis [Divides a large partition into several ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_FraigInductionPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize ) +{ + Vec_Int_t * vPart; + int i, Counter; + assert( nPartSize && Vec_IntSize(vDomain) > nPartSize ); + if ( nOverSize >= nPartSize ) + { + printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize ); + printf( "Adjusting it to be equal to half of the partition size.\n" ); + nOverSize = nPartSize/2; + } + assert( nOverSize < nPartSize ); + for ( Counter = 0; Counter < Vec_IntSize(vDomain); Counter -= nOverSize ) + { + vPart = Vec_IntAlloc( nPartSize ); + for ( i = 0; i < nPartSize; i++, Counter++ ) + if ( Counter < Vec_IntSize(vDomain) ) + Vec_IntPush( vPart, Vec_IntEntry(vDomain, Counter) ); + if ( Vec_IntSize(vPart) <= nOverSize ) + Vec_IntFree(vPart); + else + Vec_PtrPush( vResult, vPart ); + } +} + + +/**Function************************************************************* + Synopsis [Performs partitioned sequential SAT sweepingG.] Description [] @@ -260,7 +297,20 @@ Aig_Man_t * Fra_FraigInductionPart( Aig_Man_t * pAig, Fra_Ssw_t * pPars ) nPartSize = pPars->nPartSize; pPars->nPartSize = 0; fVerbose = pPars->fVerbose; pPars->fVerbose = 0; // generate partitions - vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); + if ( pAig->vClockDoms ) + { + // divide large clock domains into separate partitions + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) + { + if ( nPartSize && Vec_IntSize(vPart) > nPartSize ) + Fra_FraigInductionPartDivide( vResult, vPart, nPartSize, pPars->nOverSize ); + else + Vec_PtrPush( vResult, Vec_IntDup(vPart) ); + } + } + else + vResult = Aig_ManRegPartitionSimple( pAig, nPartSize, pPars->nOverSize ); // vResult = Aig_ManPartitionSmartRegisters( pAig, nPartSize, 0 ); // vResult = Aig_ManRegPartitionSmart( pAig, nPartSize ); if ( fPrintParts ) @@ -344,6 +394,8 @@ Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams ) if ( Aig_ManNodeNum(pManAig) == 0 ) { pParams->nIters = 0; + // Ntl_ManFinalize() needs the following to satisfy an assertion + Aig_ManReprStart(pManAig,Aig_ManObjNumMax(pManAig)); return Aig_ManDupOrdered(pManAig); } assert( Aig_ManRegNum(pManAig) > 0 ); @@ -356,7 +408,8 @@ Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, Fra_Ssw_t * pParams ) printf( "Partitioning was disabled to allow implication writing.\n" ); } // perform partitioning - if ( pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig) ) + if ( (pParams->nPartSize > 0 && pParams->nPartSize < Aig_ManRegNum(pManAig)) + || (pManAig->vClockDoms && Vec_VecSize(pManAig->vClockDoms) > 1) ) return Fra_FraigInductionPart( pManAig, pParams ); nNodesBeg = Aig_ManNodeNum(pManAig); diff --git a/src/aig/fra/fraLcr.c b/src/aig/fra/fraLcr.c index c957a751..92e0d94b 100644 --- a/src/aig/fra/fraLcr.c +++ b/src/aig/fra/fraLcr.c @@ -540,6 +540,8 @@ Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nC if ( Aig_ManNodeNum(pAig) == 0 ) { if ( pnIter ) *pnIter = 0; + // Ntl_ManFinalize() requires the following to satisfy an assertion. + Aig_ManReprStart(pAig,Aig_ManObjNumMax(pAig)); return Aig_ManDupOrdered(pAig); } assert( Aig_ManRegNum(pAig) > 0 ); diff --git a/src/aig/ntl/ntl.h b/src/aig/ntl/ntl.h index 44a9f97c..e1d3edd1 100644 --- a/src/aig/ntl/ntl.h +++ b/src/aig/ntl/ntl.h @@ -95,10 +95,11 @@ struct Ntl_Mod_t_ Vec_Ptr_t * vPos; // the array of PO objects int nObjs[NTL_OBJ_VOID]; // counter of objects of each type // box attributes - unsigned int attrWhite : 1; // box has known logic - unsigned int attrBox : 1; // box is to remain unmapped - unsigned int attrComb : 1; // box is combinational - unsigned int attrKeep : 1; // box cannot be removed by structural sweep + unsigned int attrWhite :1; // box has known logic + unsigned int attrBox :1; // box is to remain unmapped + unsigned int attrComb :1; // box is combinational + unsigned int attrKeep :1; // box cannot be removed by structural sweep + unsigned int attrNoMerge :1; // box outputs cannot be merged // hashing names into nets Ntl_Net_t ** pTable; // the hash table of names into nets int nTableSize; // the allocated table size @@ -304,7 +305,7 @@ extern ABC_DLL Aig_Man_t * Ntl_ManPrepareSec( char * pFileName1, char * pFil extern ABC_DLL Aig_Man_t * Ntl_ManExtract( Ntl_Man_t * p ); extern ABC_DLL Aig_Man_t * Ntl_ManCollapse( Ntl_Man_t * p, int fSeq ); extern ABC_DLL Aig_Man_t * Ntl_ManCollapseComb( Ntl_Man_t * p ); -extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p ); +extern ABC_DLL Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize ); /*=== ntlInsert.c ==========================================================*/ extern ABC_DLL Ntl_Man_t * Ntl_ManInsertMapping( Ntl_Man_t * p, Vec_Ptr_t * vMapping, Aig_Man_t * pAig ); extern ABC_DLL Ntl_Man_t * Ntl_ManInsertAig( Ntl_Man_t * p, Aig_Man_t * pAig ); diff --git a/src/aig/ntl/ntlExtract.c b/src/aig/ntl/ntlExtract.c index d6cbfab0..8049ffb8 100644 --- a/src/aig/ntl/ntlExtract.c +++ b/src/aig/ntl/ntlExtract.c @@ -621,7 +621,7 @@ Aig_Man_t * Ntl_ManCollapseComb( Ntl_Man_t * p ) SeeAlso [] ***********************************************************************/ -Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p ) +Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p, int nMinDomSize ) { Aig_Man_t * pAig; Ntl_Mod_t * pRoot; @@ -643,13 +643,14 @@ Aig_Man_t * Ntl_ManCollapseSeq( Ntl_Man_t * p ) // perform the traversal pAig = Ntl_ManCollapse( p, 1 ); // check if there are register classes - pAig->vClockDoms = Ntl_ManTransformRegClasses( p, 100, 1 ); + pAig->vClockDoms = Ntl_ManTransformRegClasses( p, nMinDomSize, 1 ); if ( pAig->vClockDoms ) { if ( Vec_VecSize(pAig->vClockDoms) == 0 ) printf( "Clock domains are small. Seq synthesis is not performed.\n" ); else printf( "Performing seq synthesis for %d clock domains.\n", Vec_VecSize(pAig->vClockDoms) ); + printf( "\n" ); } return pAig; } diff --git a/src/aig/ntl/ntlFraig.c b/src/aig/ntl/ntlFraig.c index 6dce3645..6449cc33 100644 --- a/src/aig/ntl/ntlFraig.c +++ b/src/aig/ntl/ntlFraig.c @@ -148,6 +148,9 @@ void Ntl_ManReduce( Ntl_Man_t * p, Aig_Man_t * pAig ) // do not reduce the net if it is driven by a multi-output box if ( Ntl_ObjIsBox(pNet->pDriver) && Ntl_ObjFanoutNum(pNet->pDriver) > 1 ) continue; + // do not reduce the net if it has no-merge attribute + if ( Ntl_ObjIsBox(pNet->pDriver) && pNet->pDriver->pImplem->attrNoMerge ) + continue; pNetRepr = pObjRepr->pData; if ( pNetRepr == NULL ) { @@ -311,7 +314,7 @@ Ntl_Man_t * Ntl_ManScl( Ntl_Man_t * p, int fLatchConst, int fLatchEqual, int fVe // collapse the AIG pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); - pAigCol = Ntl_ManCollapseSeq( pNew ); + pAigCol = Ntl_ManCollapseSeq( pNew, 0 ); //Saig_ManDumpBlif( pAigCol, "1s.blif" ); // perform SCL for the given design @@ -345,7 +348,7 @@ Ntl_Man_t * Ntl_ManLcorr( Ntl_Man_t * p, int nConfMax, int fVerbose ) // collapse the AIG pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); - pAigCol = Ntl_ManCollapseSeq( pNew ); + pAigCol = Ntl_ManCollapseSeq( pNew, 0 ); // perform SCL for the given design pTemp = Fra_FraigLatchCorrespondence( pAigCol, 0, nConfMax, 0, fVerbose, NULL, 0 ); @@ -378,7 +381,7 @@ Ntl_Man_t * Ntl_ManSsw( Ntl_Man_t * p, Fra_Ssw_t * pPars ) // collapse the AIG pAig = Ntl_ManExtract( p ); pNew = Ntl_ManInsertAig( p, pAig ); - pAigCol = Ntl_ManCollapseSeq( pNew ); + pAigCol = Ntl_ManCollapseSeq( pNew, pPars->nMinDomSize ); // perform SCL for the given design pTemp = Fra_FraigInduction( pAigCol, pPars ); @@ -554,7 +557,7 @@ Ntl_Man_t * Ntl_ManSsw2( Ntl_Man_t * p, Fra_Ssw_t * pPars ) Ntl_Man_t * pNew; Aig_Man_t * pAigRed, * pAigCol; // collapse the AIG - pAigCol = Ntl_ManCollapseSeq( p ); + pAigCol = Ntl_ManCollapseSeq( p, pPars->nMinDomSize ); // transform the collapsed AIG pAigRed = Fra_FraigInduction( pAigCol, pPars ); Aig_ManStop( pAigRed ); diff --git a/src/aig/ntl/ntlMan.c b/src/aig/ntl/ntlMan.c index cee0bf6c..06a1a51c 100644 --- a/src/aig/ntl/ntlMan.c +++ b/src/aig/ntl/ntlMan.c @@ -324,10 +324,11 @@ Ntl_Mod_t * Ntl_ModelAlloc( Ntl_Man_t * pMan, char * pName ) // start the manager p = ALLOC( Ntl_Mod_t, 1 ); memset( p, 0, sizeof(Ntl_Mod_t) ); - p->attrBox = 1; - p->attrComb = 1; - p->attrWhite = 1; - p->attrKeep = 0; + p->attrBox = 1; + p->attrComb = 1; + p->attrWhite = 1; + p->attrKeep = 0; + p->attrNoMerge = 0; p->pMan = pMan; p->pName = Ntl_ManStoreName( p->pMan, pName ); p->vObjs = Vec_PtrAlloc( 100 ); diff --git a/src/aig/ntl/ntlReadBlif.c b/src/aig/ntl/ntlReadBlif.c index ebfb2a80..cc019732 100644 --- a/src/aig/ntl/ntlReadBlif.c +++ b/src/aig/ntl/ntlReadBlif.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "ntl.h" +#include <bzlib.h> //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// @@ -41,6 +42,11 @@ struct Ioa_ReadMod_t_ Vec_Ptr_t * vTimeInputs; // .input_arrival/required lines Vec_Ptr_t * vTimeOutputs; // .output_required/arrival lines int fBlackBox; // indicates blackbox model + int fNoMerge; // indicates no-merge model + char fInArr; + char fInReq; + char fOutArr; + char fOutReq; // the resulting network Ntl_Mod_t * pNtk; // the parent manager @@ -75,6 +81,7 @@ 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 char * Ioa_ReadLoadFileBz2( 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 ); @@ -91,6 +98,7 @@ static int Ioa_ReadParseLineNamesBlif( Ioa_ReadMod_t * p, char * p 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 /// //////////////////////////////////////////////////////////////////////// @@ -125,7 +133,10 @@ Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) // start the file reader p = Ioa_ReadAlloc(); p->pFileName = pFileName; - p->pBuffer = Ioa_ReadLoadFile( pFileName ); + if ( !strncmp(pFileName+strlen(pFileName)-4,".bz2",4) ) + p->pBuffer = Ioa_ReadLoadFileBz2( pFileName ); + else + p->pBuffer = Ioa_ReadLoadFile( pFileName ); if ( p->pBuffer == NULL ) { Ioa_ReadFree( p ); @@ -173,6 +184,12 @@ Ntl_Man_t * Ioa_ReadBlif( char * pFileName, int fCheck ) // if ( (nNodes = Ntl_ManReconnectCoDrivers(pDesign)) ) // printf( "The design was transformed by removing %d buf/inv CO drivers.\n", nNodes ); //Ioa_WriteBlif( pDesign, "_temp_.blif" ); +/* + { + Aig_Man_t * p = Ntl_ManCollapseSeq( pDesign ); + Aig_ManStop( p ); + } +*/ return pDesign; } @@ -437,6 +454,91 @@ static char * Ioa_ReadLoadFile( char * pFileName ) /**Function************************************************************* + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct buflist { + char buf[1<<20]; + int nBuf; + struct buflist * next; +} buflist; + +static char * Ioa_ReadLoadFileBz2( char * pFileName ) +{ + FILE * pFile; + int nFileSize = 0; + char * pContents; + BZFILE * b; + int bzError; + struct buflist * pNext; + buflist * bufHead = NULL, * buf = NULL; + + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ioa_ReadLoadFileBz2(): The file is unavailable (absent or open).\n" ); + return NULL; + } + b = BZ2_bzReadOpen(&bzError,pFile,0,0,NULL,0); + if (bzError != BZ_OK) { + printf( "Ioa_ReadLoadFileBz2(): BZ2_bzReadOpen() failed with error %d.\n",bzError ); + return NULL; + } + do { + if (!bufHead) + buf = bufHead = ALLOC( buflist, 1 ); + else + buf = buf->next = ALLOC( buflist, 1 ); + nFileSize += buf->nBuf = BZ2_bzRead(&bzError,b,buf->buf,1<<20); + buf->next = NULL; + } while (bzError == BZ_OK); + if (bzError == BZ_STREAM_END) { + // we're okay + char * p; + int nBytes = 0; + BZ2_bzReadClose(&bzError,b); + p = pContents = ALLOC( char, nFileSize + 10 ); + buf = bufHead; + do { + memcpy(p+nBytes,buf->buf,buf->nBuf); + nBytes += buf->nBuf; +// } while((buf = buf->next)); + pNext = buf->next; + free( buf ); + } while((buf = pNext)); + } else if (bzError == BZ_DATA_ERROR_MAGIC) { + // not a BZIP2 file + BZ2_bzReadClose(&bzError,b); + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Ioa_ReadLoadFileBz2(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + } else { + // Some other error. + printf( "Ioa_ReadLoadFileBz2(): Unable to read the compressed BLIF.\n" ); + return NULL; + } + 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: @@ -485,7 +587,7 @@ static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p ) if ( !Ioa_ReadCharIsSpace(*pPrev) ) break; // if it is the line extender, overwrite it with spaces - if ( *pPrev == '\\' ) + if ( pPrev >= p->pBuffer && *pPrev == '\\' ) { for ( ; *pPrev; pPrev++ ) *pPrev = ' '; @@ -511,10 +613,22 @@ static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p ) Vec_PtrPush( p->pLatest->vDelays, pCur ); else if ( !strncmp(pCur, "input_arrival", 13) || !strncmp(pCur, "input_required", 14) ) + { + if ( !strncmp(pCur, "input_arrival", 13) ) + p->pLatest->fInArr = 1; + if ( !strncmp(pCur, "input_required", 14) ) + p->pLatest->fInReq = 1; Vec_PtrPush( p->pLatest->vTimeInputs, pCur ); - else if ( !strncmp(pCur, "output_required", 14) || - !strncmp(pCur, "output_arrival", 13) ) + } + else if ( !strncmp(pCur, "output_required", 15) || + !strncmp(pCur, "output_arrival", 14) ) + { + if ( !strncmp(pCur, "output_required", 15) ) + p->pLatest->fOutReq = 1; + if ( !strncmp(pCur, "output_arrival", 14) ) + p->pLatest->fOutArr = 1; Vec_PtrPush( p->pLatest->vTimeOutputs, pCur ); + } else if ( !strncmp(pCur, "blackbox", 8) ) p->pLatest->fBlackBox = 1; else if ( !strncmp(pCur, "model", 5) ) @@ -543,6 +657,7 @@ static void Ioa_ReadReadPreparse( Ioa_ReadMan_t * p ) } else if ( !strncmp(pCur, "no_merge", 8) ) { + p->pLatest->fNoMerge = 1; } else { @@ -579,6 +694,9 @@ static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ) // parse the model attributes if ( pMod->pAttrib && !Ioa_ReadParseLineAttrib( pMod, pMod->pAttrib ) ) return 0; + // parse no-merge + if ( pMod->fNoMerge ) + pMod->pNtk->attrNoMerge = 1; // parse the inputs Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) if ( !Ioa_ReadParseLineInputs( pMod, pLine ) ) @@ -597,6 +715,15 @@ static int Ioa_ReadReadInterfaces( Ioa_ReadMan_t * p ) Vec_PtrForEachEntry( pMod->vTimeOutputs, pLine, k ) if ( !Ioa_ReadParseLineTimes( pMod, pLine, 1 ) ) return 0; + // report timing line stats + if ( pMod->fInArr && pMod->fInReq ) + printf( "Model %s has both .input_arrival and .input_required.\n", pMod->pNtk->pName ); + if ( pMod->fOutArr && pMod->fOutReq ) + printf( "Model %s has both .output_arrival and .output_required.\n", pMod->pNtk->pName ); + if ( !pMod->vDelays && !pMod->fInArr && !pMod->fInReq ) + printf( "Model %s has neither .input_arrival nor .input_required.\n", pMod->pNtk->pName ); + if ( !pMod->vDelays && !pMod->fOutArr && !pMod->fOutReq ) + printf( "Model %s has neither .output_arrival nor .output_required.\n", pMod->pNtk->pName ); } return 1; } diff --git a/src/aig/ntl/ntlReadBlif_old.c b/src/aig/ntl/ntlReadBlif_old.c new file mode 100644 index 00000000..ebfb2a80 --- /dev/null +++ b/src/aig/ntl/ntlReadBlif_old.c @@ -0,0 +1,1261 @@ +/**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 + char * pAttrib; // .attrib 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 * vTimeInputs; // .input_arrival/required lines + Vec_Ptr_t * vTimeOutputs; // .output_required/arrival 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_ReadParseLineAttrib( 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_Man_t * pDesign; +// int nNodes; + + // 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 ); + p->pDesign->pName = Ntl_ManStoreFileName( p->pDesign, pFileName ); + p->pDesign->pSpec = Ntl_ManStoreName( p->pDesign, 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 ) + { + if ( !Ntl_ManCheck( pDesign ) ) + { + printf( "Ioa_ReadBlif: The check has failed for design %s.\n", pDesign->pName ); + Ntl_ManFree( pDesign ); + return NULL; + } + + } + // transform the design by removing the CO drivers +// if ( (nNodes = Ntl_ManReconnectCoDrivers(pDesign)) ) +// printf( "The design was transformed by removing %d buf/inv CO drivers.\n", nNodes ); +//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( 8 ); + p->vOutputs = Vec_PtrAlloc( 8 ); + p->vLatches = Vec_PtrAlloc( 8 ); + p->vNames = Vec_PtrAlloc( 8 ); + p->vSubckts = Vec_PtrAlloc( 8 ); + p->vDelays = Vec_PtrAlloc( 8 ); + p->vTimeInputs = Vec_PtrAlloc( 8 ); + p->vTimeOutputs = Vec_PtrAlloc( 8 ); + 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->vTimeInputs ); + Vec_PtrFree( p->vTimeOutputs ); + 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) || + !strncmp(pCur, "input_required", 14) ) + Vec_PtrPush( p->pLatest->vTimeInputs, pCur ); + else if ( !strncmp(pCur, "output_required", 14) || + !strncmp(pCur, "output_arrival", 13) ) + Vec_PtrPush( p->pLatest->vTimeOutputs, 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, "attrib", 6) ) + { + if ( p->pLatest->pAttrib != NULL ) + fprintf( stdout, "Line %d: Skipping second .attrib line for this model.\n", Ioa_ReadGetLine(p, pCur) ); + else + p->pLatest->pAttrib = pCur; + } + 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 if ( !strncmp(pCur, "no_merge", 8) ) + { + } + 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 model attributes + if ( pMod->pAttrib && !Ioa_ReadParseLineAttrib( pMod, pMod->pAttrib ) ) + 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->vTimeInputs, pLine, k ) + if ( !Ioa_ReadParseLineTimes( pMod, pLine, 0 ) ) + return 0; + Vec_PtrForEachEntry( pMod->vTimeOutputs, 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 ); + } + if ( i == 0 ) + return NULL; + // update the design name + pMod = Vec_PtrEntry( p->vModels, 0 ); + if ( Ntl_ModelLatchNum(pMod->pNtk) > 0 ) + Ntl_ModelTransformLatches( pMod->pNtk ); + p->pDesign->pName = Ntl_ManStoreName( p->pDesign, pMod->pNtk->pName ); + // 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 (%d) in .model line 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) ); + if ( p->pNtk == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Model %s already exists.", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens, 1) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Ioa_ReadParseLineAttrib( Ioa_ReadMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( vTokens, 0 ); + assert( !strncmp(pToken, "attrib", 6) ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + { + pToken = Vec_PtrEntry( vTokens, i ); + if ( strcmp( pToken, "white" ) == 0 ) + p->pNtk->attrWhite = 1; + else if ( strcmp( pToken, "black" ) == 0 ) + p->pNtk->attrWhite = 0; + else if ( strcmp( pToken, "box" ) == 0 ) + p->pNtk->attrBox = 1; + else if ( strcmp( pToken, "white" ) == 0 ) + p->pNtk->attrWhite = 1; + else if ( strcmp( pToken, "comb" ) == 0 ) + p->pNtk->attrComb = 1; + else if ( strcmp( pToken, "seq" ) == 0 ) + p->pNtk->attrComb = 0; + else if ( strcmp( pToken, "keep" ) == 0 ) + p->pNtk->attrKeep = 1; + else + { + sprintf( p->pMan->sError, "Line %d: Unknown attribute (%s) in the .attrib line of model %s.", Ioa_ReadGetLine(p->pMan, pToken), pToken, p->pNtk->pName ); + return 0; + } + } + 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; + 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 ) + pObj->LatchId.regInit = atoi( Vec_PtrEntry(vTokens,Vec_PtrSize(vTokens)-1) ); + else + pObj->LatchId.regInit = 2; + if ( pObj->LatchId.regInit < 0 || pObj->LatchId.regInit > 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 ) + { + pToken = Vec_PtrEntry(vTokens,3); + if ( strcmp( pToken, "fe" ) == 0 ) + pObj->LatchId.regType = 1; + else if ( strcmp( pToken, "re" ) == 0 ) + pObj->LatchId.regType = 2; + else if ( strcmp( pToken, "ah" ) == 0 ) + pObj->LatchId.regType = 3; + else if ( strcmp( pToken, "al" ) == 0 ) + pObj->LatchId.regType = 4; + else if ( strcmp( pToken, "as" ) == 0 ) + pObj->LatchId.regType = 5; + else if ( pToken[0] >= '0' && pToken[0] <= '9' ) + pObj->LatchId.regClass = atoi(pToken); + else + { + sprintf( p->pMan->sError, "Line %d: Type/class of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), pToken ); + return 0; + } + } + if ( pObj->LatchId.regClass < 0 || pObj->LatchId.regClass > (1<<24) ) + { + sprintf( p->pMan->sError, "Line %d: Class of the latch is incorrect \"%s\".", Ioa_ReadGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); + return 0; + } + // 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->pClock = 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; + } +/* + // temporary fix for splitting the .subckt line + if ( nEquals < Ntl_ModelPiNum(pModel) + Ntl_ModelPoNum(pModel) ) + { + Vec_Ptr_t * vTokens2 = Vec_PtrAlloc( 10 ); + // get one additional token + pToken = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - 1 ); + for ( ; *pToken; pToken++ ); + for ( ; *pToken == 0; pToken++ ); + Ioa_ReadSplitIntoTokensAndClear( vTokens2, pToken, '\0', '=' ); +// assert( Vec_PtrSize( vTokens2 ) == 2 ); + Vec_PtrForEachEntry( vTokens2, pToken, i ) + Vec_PtrPush( vTokens, pToken ); + nEquals += Vec_PtrSize(vTokens2)/2; + Vec_PtrFree( vTokens2 ); + } +*/ + // 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 %s differs from the sum of PIs and POs of the model (%d).", + Ioa_ReadGetLine(p->pMan, pToken), nEquals, pName, 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, 0, 0, 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, 0, 0, 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 = -1; + char * pToken, * pTokenNum; + float Delay; + assert( sizeof(float) == sizeof(int) ); + Ioa_ReadSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + if ( fOutput ) + assert( !strncmp(pToken, "output_", 7) ); + else + assert( !strncmp(pToken, "input_", 6) ); + if ( Vec_PtrSize(vTokens) != 2 && Vec_PtrSize(vTokens) != 3 ) + { + sprintf( p->pMan->sError, "Line %d: Delay line does not have a valid number of parameters (2 or 3).", Ioa_ReadGetLine(p->pMan, pToken) ); + return 0; + } + // find the delay number + pTokenNum = Vec_PtrEntryLast(vTokens); + if ( !strcmp( pTokenNum, "-inf" ) ) + Delay = -TIM_ETERNITY; + else if ( !strcmp( pTokenNum, "inf" ) ) + Delay = TIM_ETERNITY; + 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 ) + { + if ( Vec_PtrSize(vTokens) == 3 ) + { + RetValue = Ntl_ModelFindPioNumber( p->pNtk, 0, 1, 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->vTimeOutputs == NULL ) + p->pNtk->vTimeOutputs = Vec_IntAlloc( 100 ); + Vec_IntPush( p->pNtk->vTimeOutputs, Number ); + Vec_IntPush( p->pNtk->vTimeOutputs, Aig_Float2Int(Delay) ); + } + else + { + if ( Vec_PtrSize(vTokens) == 3 ) + { + RetValue = Ntl_ModelFindPioNumber( p->pNtk, 1, 0, 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->vTimeInputs == NULL ) + p->pNtk->vTimeInputs = Vec_IntAlloc( 100 ); + Vec_IntPush( p->pNtk->vTimeInputs, Number ); + Vec_IntPush( p->pNtk->vTimeInputs, 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->pMemSops, " 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->pMemSops, (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 ); + 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->pMemSops, pNode->pSop ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/src/aig/ntl/ntlTime.c b/src/aig/ntl/ntlTime.c index 53603cee..ee3e489b 100644 --- a/src/aig/ntl/ntlTime.c +++ b/src/aig/ntl/ntlTime.c @@ -91,6 +91,7 @@ void Ntl_ManUnpackLeafTiming( Ntl_Man_t * p, Tim_Man_t * pMan ) pNet->dTemp = 0; // store the PI timing vTimes = pRoot->vTimeInputs; + if ( vTimes ) Vec_IntForEachEntry( vTimes, Entry, i ) { dTime = Aig_Int2Float( Vec_IntEntry(vTimes,++i) ); @@ -172,7 +173,7 @@ Tim_Man_t * Ntl_ManCreateTiming( Ntl_Man_t * p ) Vec_Ptr_t * vDelayTables; Ntl_Mod_t * pRoot, * pModel; Ntl_Obj_t * pObj; - int i, curPi, iBox, Entry; + int i, curPi, iBox;//, Entry; assert( p->pAig != NULL ); pRoot = Ntl_ManRootModel( p ); // start the timing manager diff --git a/src/aig/ntl/ntlUtil.c b/src/aig/ntl/ntlUtil.c index 1fb9f1c6..4fd1762c 100644 --- a/src/aig/ntl/ntlUtil.c +++ b/src/aig/ntl/ntlUtil.c @@ -402,14 +402,23 @@ Vec_Vec_t * Ntl_ManTransformRegClasses( Ntl_Man_t * pMan, int nSizeMax, int fVer { printf( "The number of register clases = %d.\n", nClasses ); for ( i = 0; i <= ClassMax; i++ ) - printf( "%d:%d ", Class, pClassNums[i] ); + if ( pClassNums[i] ) + printf( "%d:%d ", i, pClassNums[i] ); printf( "\n" ); } // skip if there is only one class if ( nClasses == 1 ) { + vParts = NULL; + if ( Vec_IntSize(pMan->vRegClasses) >= nSizeMax ) + { + vParts = Vec_PtrAlloc( 100 ); + vPart = Vec_IntStartNatural( Vec_IntSize(pMan->vRegClasses) ); + Vec_PtrPush( vParts, vPart ); + } + printf( "There is only one clock domain with %d registers.\n", Vec_IntSize(pMan->vRegClasses) ); free( pClassNums ); - return NULL; + return (Vec_Vec_t *)vParts; } // create classes vParts = Vec_PtrAlloc( 100 ); diff --git a/src/aig/ntl/ntlWriteBlif.c b/src/aig/ntl/ntlWriteBlif.c index f93e3fa1..8c97d3d0 100644 --- a/src/aig/ntl/ntlWriteBlif.c +++ b/src/aig/ntl/ntlWriteBlif.c @@ -21,6 +21,13 @@ #include "ntl.h" #include "ioa.h" +#include <bzlib.h> +#include <stdarg.h> + +#ifdef _WIN32 +#define vsnprintf _vsnprintf +#endif + //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -181,7 +188,7 @@ void Ioa_WriteBlifModel( FILE * pFile, Ntl_Mod_t * pModel, int fMain ) SeeAlso [] ***********************************************************************/ -void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ) +void Ioa_WriteBlif_old( Ntl_Man_t * p, char * pFileName ) { FILE * pFile; Ntl_Mod_t * pModel; @@ -220,6 +227,264 @@ void Ioa_WriteBlifLogic( Nwk_Man_t * pNtk, Ntl_Man_t * p, char * pFileName ) Ntl_ManFree( pNew ); } + + +/**Function************************************************************* + + Synopsis [Procedure to write data into BZ2 file.] + + Description [Based on the vsnprintf() man page.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct bz2file { + FILE * f; + BZFILE * b; + char * buf; + int nBytes; + int nBytesMax; +} bz2file; + +int fprintfBz2(bz2file * b, char * fmt, ...) { + if (b->b) { + char * newBuf; + int bzError; + va_list ap; + while (1) { + va_start(ap,fmt); + b->nBytes = vsnprintf(b->buf,b->nBytesMax,fmt,ap); + va_end(ap); + if (b->nBytes > -1 && b->nBytes < b->nBytesMax) + break; + if (b->nBytes > -1) + b->nBytesMax = b->nBytes + 1; + else + b->nBytesMax *= 2; + if ((newBuf = REALLOC( char,b->buf,b->nBytesMax )) == NULL) + return -1; + else + b->buf = newBuf; + } + BZ2_bzWrite( &bzError, b->b, b->buf, b->nBytes ); + if (bzError == BZ_IO_ERROR) { + fprintf( stdout, "Ioa_WriteBlif(): I/O error writing to compressed stream.\n" ); + return -1; + } + return b->nBytes; + } else { + int n; + va_list ap; + va_start(ap,fmt); + n = vfprintf( b->f, fmt, ap); + va_end(ap); + return n; + } +} + + +/**Function************************************************************* + + Synopsis [Writes one model into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteBlifModelBz2( bz2file * b, Ntl_Mod_t * pModel, int fMain ) +{ + Ntl_Obj_t * pObj; + Ntl_Net_t * pNet; + float Delay; + int i, k; + fprintfBz2( b, ".model %s\n", pModel->pName ); + if ( pModel->attrWhite || pModel->attrBox || pModel->attrComb || pModel->attrKeep ) + { + fprintfBz2( b, ".attrib" ); + fprintfBz2( b, " %s", pModel->attrWhite? "white": "black" ); + fprintfBz2( b, " %s", pModel->attrBox? "box" : "logic" ); + fprintfBz2( b, " %s", pModel->attrComb? "comb" : "seq" ); +// fprintfBz2( b, " %s", pModel->attrKeep? "keep" : "sweep" ); + fprintfBz2( b, "\n" ); + } + fprintfBz2( b, ".inputs" ); + Ntl_ModelForEachPi( pModel, pObj, i ) + fprintfBz2( b, " %s", Ntl_ObjFanout0(pObj)->pName ); + fprintfBz2( b, "\n" ); + fprintfBz2( b, ".outputs" ); + Ntl_ModelForEachPo( pModel, pObj, i ) + fprintfBz2( b, " %s", Ntl_ObjFanin0(pObj)->pName ); + fprintfBz2( b, "\n" ); + // write delays + if ( pModel->vDelays ) + { + for ( i = 0; i < Vec_IntSize(pModel->vDelays); i += 3 ) + { + fprintfBz2( b, ".delay" ); + if ( Vec_IntEntry(pModel->vDelays,i) != -1 ) + fprintfBz2( b, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vDelays,i)))->pName ); + if ( Vec_IntEntry(pModel->vDelays,i+1) != -1 ) + fprintfBz2( b, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vDelays,i+1)))->pName ); + fprintfBz2( b, " %.3f", Aig_Int2Float(Vec_IntEntry(pModel->vDelays,i+2)) ); + fprintfBz2( b, "\n" ); + } + } + if ( pModel->vTimeInputs ) + { + for ( i = 0; i < Vec_IntSize(pModel->vTimeInputs); i += 2 ) + { + if ( fMain ) + fprintfBz2( b, ".input_arrival" ); + else + fprintfBz2( b, ".input_required" ); + if ( Vec_IntEntry(pModel->vTimeInputs,i) != -1 ) + fprintfBz2( b, " %s", Ntl_ObjFanout0(Ntl_ModelPi(pModel, Vec_IntEntry(pModel->vTimeInputs,i)))->pName ); + Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeInputs,i+1)); + if ( Delay == -TIM_ETERNITY ) + fprintfBz2( b, " -inf" ); + else if ( Delay == TIM_ETERNITY ) + fprintfBz2( b, " inf" ); + else + fprintfBz2( b, " %.3f", Delay ); + fprintfBz2( b, "\n" ); + } + } + if ( pModel->vTimeOutputs ) + { + for ( i = 0; i < Vec_IntSize(pModel->vTimeOutputs); i += 2 ) + { + if ( fMain ) + fprintfBz2( b, ".output_required" ); + else + fprintfBz2( b, ".output_arrival" ); + if ( Vec_IntEntry(pModel->vTimeOutputs,i) != -1 ) + fprintfBz2( b, " %s", Ntl_ObjFanin0(Ntl_ModelPo(pModel, Vec_IntEntry(pModel->vTimeOutputs,i)))->pName ); + Delay = Aig_Int2Float(Vec_IntEntry(pModel->vTimeOutputs,i+1)); + if ( Delay == -TIM_ETERNITY ) + fprintfBz2( b, " -inf" ); + else if ( Delay == TIM_ETERNITY ) + fprintfBz2( b, " inf" ); + else + fprintfBz2( b, " %.3f", Delay ); + fprintfBz2( b, "\n" ); + } + } + // write objects + Ntl_ModelForEachObj( pModel, pObj, i ) + { + if ( Ntl_ObjIsNode(pObj) ) + { + fprintfBz2( b, ".names" ); + Ntl_ObjForEachFanin( pObj, pNet, k ) + fprintfBz2( b, " %s", pNet->pName ); + fprintfBz2( b, " %s\n", Ntl_ObjFanout0(pObj)->pName ); + fprintfBz2( b, "%s", pObj->pSop ); + } + else if ( Ntl_ObjIsLatch(pObj) ) + { + fprintfBz2( b, ".latch" ); + fprintfBz2( b, " %s", Ntl_ObjFanin0(pObj)->pName ); + fprintfBz2( b, " %s", Ntl_ObjFanout0(pObj)->pName ); + assert( pObj->LatchId.regType == 0 || pObj->LatchId.regClass == 0 ); + if ( pObj->LatchId.regType ) + { + if ( pObj->LatchId.regType == 1 ) + fprintfBz2( b, " fe" ); + else if ( pObj->LatchId.regType == 2 ) + fprintfBz2( b, " re" ); + else if ( pObj->LatchId.regType == 3 ) + fprintfBz2( b, " ah" ); + else if ( pObj->LatchId.regType == 4 ) + fprintfBz2( b, " al" ); + else if ( pObj->LatchId.regType == 5 ) + fprintfBz2( b, " as" ); + else + assert( 0 ); + } + else if ( pObj->LatchId.regClass ) + fprintfBz2( b, " %d", pObj->LatchId.regClass ); + if ( pObj->pClock ) + fprintfBz2( b, " %s", pObj->pClock->pName ); + fprintfBz2( b, " %d", pObj->LatchId.regInit ); + fprintfBz2( b, "\n" ); + } + else if ( Ntl_ObjIsBox(pObj) ) + { + fprintfBz2( b, ".subckt %s", pObj->pImplem->pName ); + Ntl_ObjForEachFanin( pObj, pNet, k ) + fprintfBz2( b, " %s=%s", Ntl_ModelPiName(pObj->pImplem, k), pNet->pName ); + Ntl_ObjForEachFanout( pObj, pNet, k ) + fprintfBz2( b, " %s=%s", Ntl_ModelPoName(pObj->pImplem, k), pNet->pName ); + fprintfBz2( b, "\n" ); + } + } + fprintfBz2( b, ".end\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the logic network into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteBlif( Ntl_Man_t * p, char * pFileName ) +{ + Ntl_Mod_t * pModel; + int i, bzError; + + bz2file b; + memset(&b,0,sizeof(b)); + b.nBytesMax = (1<<12); + b.buf = ALLOC( char,b.nBytesMax ); + + // start the output stream + b.f = fopen( pFileName, "wb" ); + if ( b.f == NULL ) + { + fprintf( stdout, "Ioa_WriteBlif(): Cannot open the output file \"%s\".\n", pFileName ); + FREE(b.buf); + return; + } + if (!strncmp(pFileName+strlen(pFileName)-4,".bz2",4)) { + b.b = BZ2_bzWriteOpen( &bzError, b.f, 9, 0, 0 ); + if ( bzError != BZ_OK ) { + BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); + fprintf( stdout, "Ioa_WriteBlif(): Cannot start compressed stream.\n" ); + fclose( b.f ); + FREE(b.buf); + return; + } + } + + fprintfBz2( &b, "# Benchmark \"%s\" written by ABC-8 on %s\n", p->pName, Ioa_TimeStamp() ); + // write the models + Ntl_ManForEachModel( p, pModel, i ) + Ioa_WriteBlifModelBz2( &b, pModel, i==0 ); + // close the file + if (b.b) { + BZ2_bzWriteClose( &bzError, b.b, 0, NULL, NULL ); + if (bzError == BZ_IO_ERROR) { + fprintf( stdout, "Ioa_WriteBlif(): I/O error closing compressed stream.\n" ); + fclose( b.f ); + FREE(b.buf); + return; + } + } + fclose( b.f ); + FREE(b.buf); +} + + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// |