blob: 3ccfc01154b09a5c18ce3a4944ccbffe003b6e1c [file] [log] [blame]
/**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_AND2 '&'
#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 == AMAP_SYMB_AND2 )
*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