/**CFile**************************************************************** FileName [amapRead.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Technology mapper for standard cells.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: amapRead.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "amapInt.h" #include "base/io/ioAbc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AMAP_STRING_GATE "GATE" #define AMAP_STRING_PIN "PIN" #define AMAP_STRING_NONINV "NONINV" #define AMAP_STRING_INV "INV" #define AMAP_STRING_UNKNOWN "UNKNOWN" // these symbols (and no other) can appear in the formulas #define AMAP_SYMB_AND '*' #define AMAP_SYMB_OR1 '+' #define AMAP_SYMB_OR2 '|' #define AMAP_SYMB_XOR '^' #define AMAP_SYMB_NOT '!' #define AMAP_SYMB_AFTNOT '\'' #define AMAP_SYMB_OPEN '(' #define AMAP_SYMB_CLOSE ')' typedef enum { AMAP_PHASE_UNKNOWN, AMAP_PHASE_INV, AMAP_PHASE_NONINV } Amap_PinPhase_t; static inline Amap_Gat_t * Amap_ParseGateAlloc( Aig_MmFlex_t * p, int nPins ) { return (Amap_Gat_t *)Aig_MmFlexEntryFetch( p, sizeof(Amap_Gat_t)+sizeof(Amap_Pin_t)*nPins ); } static inline char * Amap_ParseStrsav( Aig_MmFlex_t * p, char * pStr ) { return pStr ? strcpy(Aig_MmFlexEntryFetch(p, strlen(pStr)+1), pStr) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Loads the file into temporary buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Amap_LoadFile( char * pFileName ) { // extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); FILE * pFile; char * pBuffer; int nFileSize; int RetValue; // open the BLIF file for binary reading pFile = Io_FileOpen( pFileName, "open_path", "rb", 1 ); // pFile = fopen( FileName, "rb" ); // if we got this far, file should be okay otherwise would // have been detected by caller if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } assert ( pFile != NULL ); // get the file size, in bytes fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); // move the file current reading position to the beginning rewind( pFile ); // load the contents of the file into memory pBuffer = ABC_ALLOC( char, nFileSize + 10 ); RetValue = fread( pBuffer, nFileSize, 1, pFile ); // terminate the string with '\0' pBuffer[ nFileSize ] = '\0'; strcat( pBuffer, "\n.end\n" ); // close file fclose( pFile ); return pBuffer; } /**Function************************************************************* Synopsis [Eliminates comments from the input file.] Description [As a byproduct, this procedure also counts the number lines and dot-statements in the input file. This also joins non-comment lines that are joined with a backspace '\'] SideEffects [] SeeAlso [] ***********************************************************************/ void Amap_RemoveComments( char * pBuffer, int * pnDots, int * pnLines ) { char * pCur; int nDots, nLines; // scan through the buffer and eliminate comments // (in the BLIF file, comments are lines starting with "#") nDots = nLines = 0; for ( pCur = pBuffer; *pCur; pCur++ ) { // if this is the beginning of comment // clean it with spaces until the new line statement if ( *pCur == '#' ) while ( *pCur != '\n' ) *pCur++ = ' '; // count the number of new lines and dots if ( *pCur == '\n' ) { if (*(pCur-1)=='\r') { // DOS(R) file support if (*(pCur-2)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-2) = ' '; *(pCur-1) = ' '; *pCur = ' '; } } else { // UNIX(TM) file support if (*(pCur-1)!='\\') nLines++; else { // rewind to backslash and overwrite with a space *(pCur-1) = ' '; *pCur = ' '; } } } else if ( *pCur == '.' ) nDots++; } if ( pnDots ) *pnDots = nDots; if ( pnLines ) *pnLines = nLines; } /**Function************************************************************* Synopsis [Splits the stream into tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_DeriveTokens( char * pBuffer ) { Vec_Ptr_t * vTokens; char * pToken; vTokens = Vec_PtrAlloc( 1000 ); pToken = strtok( pBuffer, " =\t\r\n" ); while ( pToken ) { Vec_PtrPush( vTokens, pToken ); pToken = strtok( NULL, " =\t\r\n" ); // skip latches if ( pToken && strcmp( pToken, "LATCH" ) == 0 ) while ( pToken && strcmp( pToken, "GATE" ) != 0 ) pToken = strtok( NULL, " =\t\r\n" ); } return vTokens; } /**Function************************************************************* Synopsis [Finds the number of pins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_ParseCountPins( Vec_Ptr_t * vTokens, int iPos ) { char * pToken; int i, Counter = 0; Vec_PtrForEachEntryStart( char *, vTokens, pToken, i, iPos ) if ( !strcmp( pToken, AMAP_STRING_PIN ) ) Counter++; else if ( !strcmp( pToken, AMAP_STRING_GATE ) ) return Counter; return Counter; } /**Function************************************************************* Synopsis [Collect the pin names used in the formula.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_GateCollectNames( Aig_MmFlex_t * pMem, char * pForm, char * pPinNames[] ) { char Buffer[1000]; char * pTemp; int nPins, i; // save the formula as it was strcpy( Buffer, pForm ); // remove the non-name symbols for ( pTemp = Buffer; *pTemp; pTemp++ ) if ( *pTemp == AMAP_SYMB_AND || *pTemp == AMAP_SYMB_OR1 || *pTemp == AMAP_SYMB_OR2 || *pTemp == AMAP_SYMB_XOR || *pTemp == AMAP_SYMB_NOT || *pTemp == AMAP_SYMB_OPEN || *pTemp == AMAP_SYMB_CLOSE || *pTemp == AMAP_SYMB_AFTNOT ) *pTemp = ' '; // save the names nPins = 0; pTemp = strtok( Buffer, " " ); while ( pTemp ) { for ( i = 0; i < nPins; i++ ) if ( strcmp( pTemp, pPinNames[i] ) == 0 ) break; if ( i == nPins ) { // cannot find this name; save it pPinNames[nPins++] = Amap_ParseStrsav( pMem, pTemp ); } // get the next name pTemp = strtok( NULL, " " ); } return nPins; } /**Function************************************************************* Synopsis [Creates a duplicate gate with pins specified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Gat_t * Amap_ParseGateWithSamePins( Amap_Gat_t * p ) { Amap_Gat_t * pGate; Amap_Pin_t * pPin; char * pPinNames[128]; int nPinNames; assert( p->nPins == 1 && !strcmp( p->Pins->pName, "*" ) ); nPinNames = Amap_GateCollectNames( p->pLib->pMemGates, p->pForm, pPinNames ); pGate = Amap_ParseGateAlloc( p->pLib->pMemGates, nPinNames ); *pGate = *p; pGate->nPins = nPinNames; Amap_GateForEachPin( pGate, pPin ) { *pPin = *p->Pins; pPin->pName = pPinNames[pPin - pGate->Pins]; } return pGate; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Amap_CollectFormulaTokens( Vec_Ptr_t * vTokens, char * pToken, int iPos ) { char * pNext, * pPrev; pPrev = pToken + strlen(pToken); while ( *(pPrev-1) != ';' ) { *pPrev++ = ' '; pNext = (char *)Vec_PtrEntry(vTokens, iPos++); while ( *pNext ) *pPrev++ = *pNext++; } *(pPrev-1) = 0; return iPos; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose ) { Amap_Lib_t * p; Amap_Gat_t * pGate, * pPrev; Amap_Pin_t * pPin; char * pToken, * pMoGate = NULL; int i, nPins, iPos = 0, Count = 0; p = Amap_LibAlloc(); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); do { if ( strcmp( pToken, AMAP_STRING_GATE ) ) { Amap_LibFree( p ); printf( "The first line should begin with %s.\n", AMAP_STRING_GATE ); return NULL; } // start gate nPins = Amap_ParseCountPins( vTokens, iPos ); pGate = Amap_ParseGateAlloc( p->pMemGates, nPins ); memset( pGate, 0, sizeof(Amap_Gat_t) ); pGate->Id = Vec_PtrSize( p->vGates ); Vec_PtrPush( p->vGates, pGate ); pGate->pLib = p; pGate->nPins = nPins; // read gate pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->pName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->dArea = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pGate->pOutName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); iPos = Amap_CollectFormulaTokens( vTokens, pToken, iPos ); pGate->pForm = Amap_ParseStrsav( p->pMemGates, pToken ); // read pins Amap_GateForEachPin( pGate, pPin ) { pToken = (char *)Vec_PtrEntry(vTokens, iPos++); if ( strcmp( pToken, AMAP_STRING_PIN ) ) { Amap_LibFree( p ); printf( "Cannot parse gate %s.\n", pGate->pName ); return NULL; } // read pin pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->pName = Amap_ParseStrsav( p->pMemGates, pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); if ( strcmp( pToken, AMAP_STRING_UNKNOWN ) == 0 ) pPin->Phase = AMAP_PHASE_UNKNOWN; else if ( strcmp( pToken, AMAP_STRING_INV ) == 0 ) pPin->Phase = AMAP_PHASE_INV; else if ( strcmp( pToken, AMAP_STRING_NONINV ) == 0 ) pPin->Phase = AMAP_PHASE_NONINV; else { Amap_LibFree( p ); printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName ); return NULL; } pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dLoadInput = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dLoadMax = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayBlockRise = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayFanoutRise = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayBlockFall = atof( pToken ); pToken = (char *)Vec_PtrEntry(vTokens, iPos++); pPin->dDelayFanoutFall = atof( pToken ); if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) pPin->dDelayBlockMax = pPin->dDelayBlockRise; else pPin->dDelayBlockMax = pPin->dDelayBlockFall; } // fix the situation when all pins are represented as one if ( pGate->nPins == 1 && !strcmp( pGate->Pins->pName, "*" ) ) { pGate = Amap_ParseGateWithSamePins( pGate ); Vec_PtrPop( p->vGates ); Vec_PtrPush( p->vGates, pGate ); } pToken = (char *)Vec_PtrEntry(vTokens, iPos++); //printf( "Finished reading gate %s (%s)\n", pGate->pName, pGate->pOutName ); } while ( strcmp( pToken, ".end" ) ); // check if there are gates with identical names pPrev = NULL; Amap_LibForEachGate( p, pGate, i ) { if ( pPrev && !strcmp(pPrev->pName, pGate->pName) ) { pPrev->pTwin = pGate, pGate->pTwin = pPrev; // printf( "Warning: Detected multi-output gate \"%s\".\n", pGate->pName ); if ( pMoGate == NULL ) pMoGate = pGate->pName; Count++; } pPrev = pGate; } if ( Count ) printf( "Warning: Detected %d multi-output gates (for example, \"%s\").\n", Count, pMoGate ); return p; } /**Function************************************************************* Synopsis [Reads the library from the input file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibReadBuffer( char * pBuffer, int fVerbose ) { Amap_Lib_t * pLib; Vec_Ptr_t * vTokens; Amap_RemoveComments( pBuffer, NULL, NULL ); vTokens = Amap_DeriveTokens( pBuffer ); pLib = Amap_ParseTokens( vTokens, fVerbose ); if ( pLib == NULL ) { Vec_PtrFree( vTokens ); return NULL; } Vec_PtrFree( vTokens ); return pLib; } /**Function************************************************************* Synopsis [Reads the library from the input file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Amap_Lib_t * Amap_LibReadFile( char * pFileName, int fVerbose ) { Amap_Lib_t * pLib; char * pBuffer; pBuffer = Amap_LoadFile( pFileName ); if ( pBuffer == NULL ) return NULL; pLib = Amap_LibReadBuffer( pBuffer, fVerbose ); if ( pLib ) pLib->pName = Abc_UtilStrsav( pFileName ); ABC_FREE( pBuffer ); return pLib; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END