#include "wlc.h"
ABC_NAMESPACE_IMPL_START
#define WLV_PRS_MAX_LINE 10000
typedef struct Wlc_Prs_t_ Wlc_Prs_t;
struct Wlc_Prs_t_
{
int nFileSize;
char * pFileName;
char * pBuffer;
Vec_Int_t * vLines;
Vec_Int_t * vStarts;
Vec_Int_t * vFanins;
Wlc_Ntk_t * pNtk;
Mem_Flex_t * pMemTable;
Vec_Ptr_t * vTables;
Vec_Str_t * vPoPairs;
int nConsts;
int nNonZero[4];
int nNegative[4];
int nReverse[4];
char sError[WLV_PRS_MAX_LINE];
};
static inline int Wlc_PrsOffset( Wlc_Prs_t * p, char * pStr ) { return pStr - p->pBuffer; }
static inline char * Wlc_PrsStr( Wlc_Prs_t * p, int iOffset ) { return p->pBuffer + iOffset; }
static inline int Wlc_PrsStrCmp( char * pStr, char * pWhat ) { return !strncmp( pStr, pWhat, strlen(pWhat)); }
#define Wlc_PrsForEachLine( p, pLine, i ) \
for ( i = 0; (i < Vec_IntSize((p)->vStarts)) && ((pLine) = Wlc_PrsStr(p, Vec_IntEntry((p)->vStarts, i))); i++ )
#define Wlc_PrsForEachLineStart( p, pLine, i, Start ) \
for ( i = Start; (i < Vec_IntSize((p)->vStarts)) && ((pLine) = Wlc_PrsStr(p, Vec_IntEntry((p)->vStarts, i))); i++ )
Wlc_Prs_t * Wlc_PrsStart( char * pFileName, char * pStr )
{
Wlc_Prs_t * p;
if ( pFileName && !Extra_FileCheck( pFileName ) )
return NULL;
p = ABC_CALLOC( Wlc_Prs_t, 1 );
p->pFileName = pFileName;
p->pBuffer = pStr ? Abc_UtilStrsav(pStr) : Extra_FileReadContents( pFileName );
p->nFileSize = strlen(p->pBuffer); assert( p->nFileSize > 0 );
p->vLines = Vec_IntAlloc( p->nFileSize / 50 );
p->vStarts = Vec_IntAlloc( p->nFileSize / 50 );
p->vFanins = Vec_IntAlloc( 100 );
p->vTables = Vec_PtrAlloc( 1000 );
p->pMemTable = Mem_FlexStart();
return p;
}
void Wlc_PrsStop( Wlc_Prs_t * p )
{
if ( p->pNtk )
Wlc_NtkFree( p->pNtk );
if ( p->pMemTable )
Mem_FlexStop( p->pMemTable, 0 );
Vec_StrFreeP( &p->vPoPairs );
Vec_PtrFreeP( &p->vTables );
Vec_IntFree( p->vLines );
Vec_IntFree( p->vStarts );
Vec_IntFree( p->vFanins );
ABC_FREE( p->pBuffer );
ABC_FREE( p );
}
int Wlc_PrsFindLine( Wlc_Prs_t * p, char * pCur )
{
int Entry, iLine = 0;
Vec_IntForEachEntry( p->vLines, Entry, iLine )
if ( Entry > pCur - p->pBuffer )
return iLine + 1;
return -1;
}
int Wlc_PrsWriteErrorMessage( Wlc_Prs_t * p, char * pCur, const char * format, ... )
{
char * pMessage;
va_list args;
va_start( args, format );
pMessage = vnsprintf( format, args );
va_end( args );
assert( strlen(pMessage) < WLV_PRS_MAX_LINE - 100 );
assert( p->sError[0] == 0 );
if ( pCur == NULL ) sprintf( p->sError, "%s: %s\n", p->pFileName, pMessage );
else {
int iLine = Wlc_PrsFindLine( p, pCur );
sprintf( p->sError, "%s (line %d): %s\n", p->pFileName, iLine, pMessage );
}
ABC_FREE( pMessage );
return 0;
}
void Wlc_PrsPrintErrorMessage( Wlc_Prs_t * p )
{
if ( p->sError[0] == 0 )
return;
fprintf( stdout, "%s", p->sError );
}
static inline int Wlc_PrsIsDigit( char * pStr )
{
return (pStr[0] >= '0' && pStr[0] <= '9');
}
static inline int Wlc_PrsIsChar( char * pStr )
{
return (pStr[0] >= 'a' && pStr[0] <= 'z') ||
(pStr[0] >= 'A' && pStr[0] <= 'Z') ||
(pStr[0] >= '0' && pStr[0] <= '9') ||
pStr[0] == '_' || pStr[0] == '$' || pStr[0] == '\\';
}
static inline char * Wlc_PrsSkipSpaces( char * pStr )
{
while ( *pStr && *pStr == ' ' )
pStr++;
return pStr;
}
static inline char * Wlc_PrsFindSymbol( char * pStr, char Symb )
{
int fNotName = 1;
for ( ; *pStr; pStr++ )
{
if ( fNotName && *pStr == Symb )
return pStr;
if ( pStr[0] == '\\' )
fNotName = 0;
else if ( !fNotName && *pStr == ' ' )
fNotName = 1;
}
return NULL;
}
static inline char * Wlc_PrsFindSymbolTwo( char * pStr, char Symb, char Symb2 )
{
for ( ; pStr[1]; pStr++ )
if ( pStr[0] == Symb && pStr[1] == Symb2 )
return pStr;
return NULL;
}
static inline char * Wlc_PrsFindClosingParenthesis( char * pStr, char Open, char Close )
{
int Counter = 0;
int fNotName = 1;
assert( *pStr == Open );
for ( ; *pStr; pStr++ )
{
if ( fNotName )
{
if ( *pStr == Open )
Counter++;
if ( *pStr == Close )
Counter--;
if ( Counter == 0 )
return pStr;
}
if ( *pStr == '\\' )
fNotName = 0;
else if ( !fNotName && *pStr == ' ' )
fNotName = 1;
}
return NULL;
}
int Wlc_PrsRemoveComments( Wlc_Prs_t * p )
{
int fSpecifyFound = 0;
char * pCur, * pNext, * pEnd = p->pBuffer + p->nFileSize;
for ( pCur = p->pBuffer; pCur < pEnd; pCur++ )
{
if ( *pCur == '/' && pCur[1] == '/' )
{
if ( pCur + 5 < pEnd && pCur[2] == 'a' && pCur[3] == 'b' && pCur[4] == 'c' && pCur[5] == '2' )
pCur[0] = pCur[1] = pCur[2] = pCur[3] = pCur[4] = pCur[5] = ' ';
else if ( !strncmp(pCur + 3, "Pair:", 5) )
{
if ( p->vPoPairs == NULL )
p->vPoPairs = Vec_StrAlloc( 100 );
for ( pNext = pCur + 9; *pNext != '\n'; pNext++ )
{
if ( *pNext == ' ' )
Vec_StrPush( p->vPoPairs, '\0' );
else if ( *pNext != '\r' )
Vec_StrPush( p->vPoPairs, *pNext );
}
if ( Vec_StrEntryLast(p->vPoPairs) != 0 )
Vec_StrPush(p->vPoPairs, 0);
}
else
{
pNext = Wlc_PrsFindSymbol( pCur, '\n' );
if ( pNext == NULL )
return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find end-of-line after symbols \"//\"." );
for ( ; pCur < pNext; pCur++ )
*pCur = ' ';
}
}
else if ( *pCur == '`' )
{
pNext = Wlc_PrsFindSymbol( pCur, '\n' );
if ( pNext == NULL )
return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find end-of-line after symbols \"`\"." );
for ( ; pCur < pNext; pCur++ )
*pCur = ' ';
}
else if ( *pCur == '/' && pCur[1] == '*' )
{
pNext = Wlc_PrsFindSymbolTwo( pCur, '*', '/' );
if ( pNext == NULL )
return Wlc_PrsWriteErrorMessage( p, pCur, "Cannot find symbols \"*/\" after symbols \"/*\"." );
for ( ; pCur < pNext + 2; pCur++ )
*pCur = ' ';
}
else if ( *pCur == 's' && pCur[1] == 'p' && pCur[2] == 'e' && !strncmp(pCur, "specify", 7) )
{
for ( pNext = pCur; pNext < pEnd - 10; pNext++ )
if ( *pNext == 'e' && pNext[1] == 'n' && pNext[2] == 'd' && !strncmp(pNext, "endspecify", 10) )
{
for ( ; pCur < pNext + 10; pCur++ )
*pCur = ' ';
if ( fSpecifyFound == 0 )
Abc_Print( 0, "Ignoring specify/endspecify directives.\n" );
fSpecifyFound = 1;
break;
}
}
else if ( *pCur == 'e' && pCur[1] == 'n' && pCur[2] == 'd' && !strncmp(pCur, "endmodule", 9) )
pCur[strlen("endmodule")] = ';';
if ( *pCur == '\n' || *pCur == '\r' || *pCur == '\t' )
*pCur = ' ';
}
return 1;
}
int Wlc_PrsPrepare( Wlc_Prs_t * p )
{
int fPrettyPrint = 0;
int fNotName = 1;
char * pTemp, * pPrev, * pThis;
assert( Vec_IntSize(p->vLines) == 0 );
for ( pTemp = p->pBuffer; *pTemp; pTemp++ )
if ( *pTemp == '\n' )
Vec_IntPush( p->vLines, pTemp - p->pBuffer );
if ( !Wlc_PrsRemoveComments( p ) )
return 0;
assert( Vec_IntSize(p->vStarts) == 0 );
for ( pPrev = pThis = p->pBuffer; *pThis; pThis++ )
{
if ( fNotName && *pThis == ';' )
{
*pThis = 0;
Vec_IntPush( p->vStarts, Wlc_PrsOffset(p, Wlc_PrsSkipSpaces(pPrev)) );
pPrev = pThis + 1;
}
if ( *pThis == '\\' )
fNotName = 0;
else if ( !fNotName && *pThis == ' ' )
fNotName = 1;
}
if ( fPrettyPrint )
{
int i, k;
Wlc_PrsForEachLine( p, pTemp, i )
{
if ( Wlc_PrsStrCmp( pTemp, "module" ) )
printf( "\n" );
if ( !Wlc_PrsStrCmp( pTemp, "module" ) && !Wlc_PrsStrCmp( pTemp, "endmodule" ) )
printf( " " );
printf( "%c", pTemp[0] );
for ( k = 1; pTemp[k]; k++ )
if ( pTemp[k] != ' ' || pTemp[k-1] != ' ' )
printf( "%c", pTemp[k] );
printf( ";\n" );
}
}
return 1;
}
char * Wlc_PrsStrtok( char * s, const char * delim )
{
const char *spanp;
int c, sc;
char *tok;
static char *last;
if (s == NULL && (s = last) == NULL)
return NULL;
cont:
c = *s++;
for (spanp = delim; (sc = *spanp++) != 0;)
if (c == sc)
goto cont;
if (c == 0) return (last = NULL);
if ( c != '\\' )
tok = s - 1;
else
tok = s - 1;
s--;
for (;;)
{
c = *s++;
if ( c == '\\' ) {
while ( c != ' ' )
c = *s++;
c = *s++;
}
spanp = delim;
do {
if ((sc = *spanp++) == c)
{
if (c == 0)
s = NULL;
else
s[-1] = 0;
last = s;
return (tok);
}
} while (sc != 0);
}
return NULL;
}
char * Wlc_PrsConvertInitValues( Wlc_Ntk_t * p )
{
Wlc_Obj_t * pObj;
int i, k, Value, * pInits;
char * pResult;
Vec_Str_t * vStr = Vec_StrAlloc( 1000 );
Vec_IntForEachEntry( p->vInits, Value, i )
{
if ( Value < 0 )
{
for ( k = 0; k < -Value; k++ )
Vec_StrPush( vStr, '0' );
continue;
}
pObj = Wlc_NtkObj( p, Value );
Value = Wlc_ObjRange(pObj);
while ( pObj->Type == WLC_OBJ_BUF )
pObj = Wlc_NtkObj( p, Wlc_ObjFaninId0(pObj) );
pInits = (pObj->Type == WLC_OBJ_CONST && !pObj->fXConst) ? Wlc_ObjConstValue(pObj) : NULL;
for ( k = 0; k < Abc_MinInt(Value, Wlc_ObjRange(pObj)); k++ )
Vec_StrPush( vStr, (char)(pInits ? '0' + Abc_InfoHasBit((unsigned *)pInits, k) : 'x') );
for ( ; k < Value; k++ )
Vec_StrPush( vStr, '0' );
Vec_IntWriteEntry( p->vInits, i, (pInits || pObj->fXConst) ? -Value : Wlc_ObjCiId(pObj) );
}
Vec_StrPush( vStr, '\0' );
pResult = Vec_StrReleaseArray( vStr );
Vec_StrFree( vStr );
return pResult;
}
int Wlc_PrsCheckBitConst0( Wlc_Ntk_t * p, int NameId )
{
Wlc_Obj_t * pObj = Wlc_NtkObj( p, NameId );
int * pInits;
if ( Wlc_ObjRange(pObj) != 1 )
return 0;
while ( pObj->Type == WLC_OBJ_BUF )
pObj = Wlc_NtkObj( p, Wlc_ObjFaninId0(pObj) );
if ( pObj->Type != WLC_OBJ_CONST )
return 0;
pInits = Wlc_ObjConstValue(pObj);
return Abc_InfoHasBit((unsigned *)pInits, 0) == 0;
}
static inline char * Wlc_PrsFindRange( char * pStr, int * End, int * Beg )
{
*End = *Beg = 0;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( pStr[0] != '[' )
return pStr;
pStr = Wlc_PrsSkipSpaces( pStr+1 );
if ( !Wlc_PrsIsDigit(pStr) && pStr[0] != '-' )
return NULL;
*End = *Beg = atoi( pStr );
if ( Wlc_PrsFindSymbol( pStr, ':' ) == NULL )
{
pStr = Wlc_PrsFindSymbol( pStr, ']' );
if ( pStr == NULL )
return NULL;
}
else
{
pStr = Wlc_PrsFindSymbol( pStr, ':' );
pStr = Wlc_PrsSkipSpaces( pStr+1 );
if ( !Wlc_PrsIsDigit(pStr) && pStr[0] != '-' )
return NULL;
*Beg = atoi( pStr );
pStr = Wlc_PrsFindSymbol( pStr, ']' );
if ( pStr == NULL )
return NULL;
}
return pStr + 1;
}
static inline char * Wlc_PrsFindWord( char * pStr, char * pWord, int * fFound )
{
*fFound = 0;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( !Wlc_PrsStrCmp(pStr, pWord) )
return pStr;
*fFound = 1;
return pStr + strlen(pWord);
}
static inline char * Wlc_PrsFindName( char * pStr, char ** ppPlace )
{
static char Buffer[WLV_PRS_MAX_LINE];
char * pThis = *ppPlace = Buffer;
int fNotName = 1, Count = 0;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( !Wlc_PrsIsChar(pStr) )
return NULL;
while ( *pStr )
{
if ( fNotName && !Wlc_PrsIsChar(pStr) )
break;
if ( *pStr == '\\' )
{
Count++;
fNotName = 0;
}
else if ( !fNotName && *pStr == ' ' )
{
Count--;
if ( !Count )
fNotName = 1;
}
*pThis++ = *pStr++;
}
*pThis = 0;
return pStr;
}
static inline char * Wlc_PrsReadConstant( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins, int * pRange, int * pSigned, int * pXValue )
{
int i, nDigits, nBits = atoi( pStr );
*pRange = -1;
*pSigned = 0;
*pXValue = 0;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( Wlc_PrsFindSymbol( pStr, '\'' ) == NULL )
{
int Number = atoi( pStr );
*pRange = Abc_Base2Log( Number+1 );
assert( *pRange < 32 );
while ( Wlc_PrsIsDigit(pStr) )
pStr++;
Vec_IntFill( vFanins, 1, Number );
return pStr;
}
pStr = Wlc_PrsFindSymbol( pStr, '\'' );
if ( pStr[1] == 's' )
{
*pSigned = 1;
pStr++;
}
if ( pStr[1] == 'b' )
{
Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 );
for ( i = 0; i < nBits; i++ )
if ( pStr[2+i] == '1' )
Abc_InfoSetBit( (unsigned *)Vec_IntArray(vFanins), nBits-1-i );
else if ( pStr[2+i] != '0' )
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Wrong digit in binary constant \"%c\".", pStr[2+i] );
*pRange = nBits;
pStr += 2 + nBits;
return pStr;
}
if ( pStr[1] != 'h' )
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Expecting hexadecimal constant and not \"%c\".", pStr[1] );
*pXValue = (pStr[2] == 'x' || pStr[2] == 'X');
if ( *pXValue == 'X' )
*pXValue = 'x';
Vec_IntFill( vFanins, Abc_BitWordNum(nBits), 0 );
nDigits = Abc_TtReadHexNumber( (word *)Vec_IntArray(vFanins), pStr+2 );
if ( nDigits != (nBits + 3)/4 )
{
}
*pRange = nBits;
pStr += 2;
while ( Wlc_PrsIsChar(pStr) )
pStr++;
return pStr;
}
static inline char * Wlc_PrsReadName( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins )
{
int NameId, fFound, iObj;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( Wlc_PrsIsDigit(pStr) )
{
char Buffer[100];
int Range, Signed, XValue = 0;
Vec_Int_t * vFanins = Vec_IntAlloc(0);
pStr = Wlc_PrsReadConstant( p, pStr, vFanins, &Range, &Signed, &XValue );
if ( pStr == NULL )
{
Vec_IntFree( vFanins );
return 0;
}
iObj = Wlc_ObjAlloc( p->pNtk, WLC_OBJ_CONST, Signed, Range-1, 0 );
Wlc_ObjAddFanins( p->pNtk, Wlc_NtkObj(p->pNtk, iObj), vFanins );
Wlc_NtkObj(p->pNtk, iObj)->fXConst = XValue;
Vec_IntFree( vFanins );
sprintf( Buffer, "_c%d_", p->nConsts++ );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, Buffer, &fFound );
if ( fFound )
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is already used.", Buffer );
assert( iObj == NameId );
}
else
{
char * pName;
pStr = Wlc_PrsFindName( pStr, &pName );
if ( pStr == NULL )
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in assign-statement." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return (char *)(ABC_PTRINT_T)Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is used but not declared.", pName );
}
Vec_IntPush( vFanins, NameId );
return Wlc_PrsSkipSpaces( pStr );
}
static inline int Wlc_PrsFindDefinition( Wlc_Prs_t * p, char * pStr, Vec_Int_t * vFanins, int * pXValue )
{
char * pName;
int Type = WLC_OBJ_NONE;
int fRotating = 0;
Vec_IntClear( vFanins );
pStr = Wlc_PrsSkipSpaces( pStr );
if ( pStr[0] != '=' )
return 0;
pStr = Wlc_PrsSkipSpaces( pStr+1 );
if ( pStr[0] == '(' )
{
if ( Wlc_PrsFindSymbolTwo(pStr, '>', '>') && Wlc_PrsFindSymbolTwo(pStr, '<', '<') )
{
char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' );
if ( pClose == NULL )
return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." );
*pStr = ' '; *pClose = 0;
pStr = Wlc_PrsSkipSpaces( pStr );
fRotating = 1;
}
else
{
char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' );
if ( pClose == NULL )
return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." );
*pStr = *pClose = ' ';
pStr = Wlc_PrsSkipSpaces( pStr );
}
}
if ( Wlc_PrsIsDigit(pStr) )
{
int Range, Signed;
pStr = Wlc_PrsReadConstant( p, pStr, vFanins, &Range, &Signed, pXValue );
if ( pStr == NULL )
return 0;
Type = WLC_OBJ_CONST;
}
else if ( pStr[0] == '!' || (pStr[0] == '~' && pStr[1] != '&' && pStr[1] != '|' && pStr[1] != '^') || pStr[0] == '@' || pStr[0] == '#' )
{
if ( pStr[0] == '!' )
Type = WLC_OBJ_LOGIC_NOT;
else if ( pStr[0] == '~' )
Type = WLC_OBJ_BIT_NOT;
else if ( pStr[0] == '@' )
Type = WLC_OBJ_ARI_SQRT;
else if ( pStr[0] == '#' )
Type = WLC_OBJ_ARI_SQUARE;
else assert( 0 );
pStr = Wlc_PrsSkipSpaces( pStr+1 );
if ( pStr[0] == '(' )
{
char * pClose = Wlc_PrsFindClosingParenthesis( pStr, '(', ')' );
if ( pClose == NULL )
return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting closing parenthesis." );
*pStr = *pClose = ' ';
}
if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name after !." );
}
else if ( pStr[0] == '-' ||
pStr[0] == '&' || pStr[0] == '|' || pStr[0] == '^' ||
(pStr[0] == '~' && pStr[1] == '&') ||
(pStr[0] == '~' && pStr[1] == '|') ||
(pStr[0] == '~' && pStr[1] == '^') )
{
int shift = 1;
if ( pStr[0] == '-' )
Type = WLC_OBJ_ARI_MINUS;
else if ( pStr[0] == '&' )
Type = WLC_OBJ_REDUCT_AND;
else if ( pStr[0] == '|' )
Type = WLC_OBJ_REDUCT_OR;
else if ( pStr[0] == '^' )
Type = WLC_OBJ_REDUCT_XOR;
else if ( pStr[0] == '~' && pStr[1] == '&' )
{Type = WLC_OBJ_REDUCT_NAND; shift = 2;}
else if ( pStr[0] == '~' && pStr[1] == '|' )
{Type = WLC_OBJ_REDUCT_NOR; shift = 2;}
else if ( pStr[0] == '~' && pStr[1] == '^' )
{Type = WLC_OBJ_REDUCT_NXOR; shift = 2;}
else assert( 0 );
if ( !(pStr = Wlc_PrsReadName(p, pStr+shift, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name after a unary operator." );
}
else if ( pStr[0] == '{' )
{
if ( Wlc_PrsFindSymbol(pStr+1, '{') )
{
if ( Wlc_PrsFindSymbol(pStr+1, '\'') )
Type = WLC_OBJ_BIT_ZEROPAD;
else
Type = WLC_OBJ_BIT_SIGNEXT;
pStr = Wlc_PrsFindSymbol(pStr+1, ',');
if ( pStr == NULL )
return Wlc_PrsWriteErrorMessage( p, pStr, "Expecting one comma in this line." );
if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in sign-extension." );
pStr = Wlc_PrsSkipSpaces( pStr );
if ( pStr[0] != '}' )
return Wlc_PrsWriteErrorMessage( p, pStr, "There is no closing brace (})." );
}
else {
while ( 1 )
{
pStr = Wlc_PrsSkipSpaces( pStr+1 );
if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in concatenation." );
if ( pStr[0] == '}' )
break;
if ( pStr[0] != ',' )
return Wlc_PrsWriteErrorMessage( p, pStr, "Expected comma (,) in this place." );
}
Type = WLC_OBJ_BIT_CONCAT;
}
assert( pStr[0] == '}' );
pStr++;
}
else
{
if ( !(pStr = Wlc_PrsReadName(p, pStr, vFanins)) )
return 0;
if ( pStr[0] == 0 )
Type = WLC_OBJ_BUF;
else if ( pStr[0] == '?' )
{
if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in MUX." );
if ( pStr[0] != ':' )
return Wlc_PrsWriteErrorMessage( p, pStr, "MUX lacks the colon symbol (:)." );
if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) )
return Wlc_PrsWriteErrorMessage( p, pStr, "Cannot read name in MUX." );
assert( Vec_IntSize(vFanins) == 3 );
ABC_SWAP( int, Vec_IntArray(vFanins)[1], Vec_IntArray(vFanins)[2] );
Type = WLC_OBJ_MUX;
}
else if ( pStr[0] == '[' )
{
int End, Beg; char * pLine = pStr;
pStr = Wlc_PrsFindRange( pStr, &End, &Beg );
if ( pStr == NULL )
return Wlc_PrsWriteErrorMessage( p, pLine, "Non-standard range." );
Vec_IntPushTwo( vFanins, End, Beg );
Type = WLC_OBJ_BIT_SELECT;
}
else
{
if ( pStr[0] == '>' && pStr[1] == '>' && pStr[2] != '>' ) pStr += 2, Type = fRotating ? WLC_OBJ_ROTATE_R : WLC_OBJ_SHIFT_R;
else if ( pStr[0] == '>' && pStr[1] == '>' && pStr[2] == '>' ) pStr += 3, Type = WLC_OBJ_SHIFT_RA;
else if ( pStr[0] == '<' && pStr[1] == '<' && pStr[2] != '<' ) pStr += 2, Type = fRotating ? WLC_OBJ_ROTATE_L : WLC_OBJ_SHIFT_L;
else if ( pStr[0] == '<' && pStr[1] == '<' && pStr[2] == '<' ) pStr += 3, Type = WLC_OBJ_SHIFT_LA;
else if ( pStr[0] == '&' && pStr[1] != '&' ) pStr += 1, Type = WLC_OBJ_BIT_AND;
else if ( pStr[0] == '|' && pStr[1] != '|' ) pStr += 1, Type = WLC_OBJ_BIT_OR;
else if ( pStr[0] == '^' && pStr[1] != '^' ) pStr += 1, Type = WLC_OBJ_BIT_XOR;
else if ( pStr[0] == '~' && pStr[1] == '&' ) pStr += 2, Type = WLC_OBJ_BIT_NAND;
else if ( pStr[0] == '~' && pStr[1] == '|' ) pStr += 2, Type = WLC_OBJ_BIT_NOR;
else if ( pStr[0] == '~' && pStr[1] == '^' ) pStr += 2, Type = WLC_OBJ_BIT_NXOR;
else if ( pStr[0] == '=' && pStr[1] == '>' ) pStr += 2, Type = WLC_OBJ_LOGIC_IMPL;
else if ( pStr[0] == '&' && pStr[1] == '&' ) pStr += 2, Type = WLC_OBJ_LOGIC_AND;
else if ( pStr[0] == '|' && pStr[1] == '|' ) pStr += 2, Type = WLC_OBJ_LOGIC_OR;
else if ( pStr[0] == '^' && pStr[1] == '^' ) pStr += 2, Type = WLC_OBJ_LOGIC_XOR;
else if ( pStr[0] == '=' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_EQU;
else if ( pStr[0] == '!' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_NOTEQU;
else if ( pStr[0] == '<' && pStr[1] != '=' ) pStr += 1, Type = WLC_OBJ_COMP_LESS;
else if ( pStr[0] == '>' && pStr[1] != '=' ) pStr += 1, Type = WLC_OBJ_COMP_MORE;
else if ( pStr[0] == '<' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_LESSEQU;
else if ( pStr[0] == '>' && pStr[1] == '=' ) pStr += 2, Type = WLC_OBJ_COMP_MOREEQU;
else if ( pStr[0] == '+' ) pStr += 1, Type = WLC_OBJ_ARI_ADD;
else if ( pStr[0] == '-' ) pStr += 1, Type = WLC_OBJ_ARI_SUB;
else if ( pStr[0] == '*' && pStr[1] != '*' ) pStr += 1, Type = WLC_OBJ_ARI_MULTI;
else if ( pStr[0] == '/' ) pStr += 1, Type = WLC_OBJ_ARI_DIVIDE;
else if ( pStr[0] == '%' ) pStr += 1, Type = WLC_OBJ_ARI_REM;
else if ( pStr[0] == '*' && pStr[1] == '*' ) pStr += 2, Type = WLC_OBJ_ARI_POWER;
else return Wlc_PrsWriteErrorMessage( p, pStr, "Unsupported operation (%c).", pStr[0] );
if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) )
return 0;
pStr = Wlc_PrsSkipSpaces( pStr );
if ( Type == WLC_OBJ_ARI_ADD && pStr[0] == '+' )
{
if ( !(pStr = Wlc_PrsReadName(p, pStr+1, vFanins)) )
return 0;
pStr = Wlc_PrsSkipSpaces( pStr );
}
if ( pStr[0] )
printf( "Warning: Trailing symbols \"%s\" in line %d.\n", pStr, Wlc_PrsFindLine(p, pStr) );
}
}
if ( pStr )
{
pStr = Wlc_PrsFindName( pStr, &pName );
if ( pStr != NULL )
return Wlc_PrsWriteErrorMessage( p, pStr, "Name %s is left at the end of the line.", pName );
}
return Type;
}
int Wlc_PrsReadDeclaration( Wlc_Prs_t * p, char * pStart )
{
int fFound = 0, Type = WLC_OBJ_NONE, iObj; char * pLine;
int Signed = 0, Beg = 0, End = 0, NameId, fIsPo = 0;
if ( Wlc_PrsStrCmp( pStart, "input" ) )
pStart += strlen("input"), Type = WLC_OBJ_PI;
else if ( Wlc_PrsStrCmp( pStart, "output" ) )
pStart += strlen("output"), fIsPo = 1;
pStart = Wlc_PrsSkipSpaces( pStart );
if ( Wlc_PrsStrCmp( pStart, "wire" ) )
pStart += strlen("wire");
else if ( Wlc_PrsStrCmp( pStart, "reg" ) )
pStart += strlen("reg");
pStart = Wlc_PrsFindWord( pStart, "signed", &Signed );
pLine = pStart;
pStart = Wlc_PrsFindRange( pStart, &End, &Beg );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pLine, "Non-standard range." );
if ( End != 0 && Beg != 0 )
{
if ( p->nNonZero[0]++ == 0 )
{
p->nNonZero[1] = End;
p->nNonZero[2] = Beg;
p->nNonZero[3] = Wlc_PrsFindLine(p, pStart);
}
}
if ( End < 0 || Beg < 0 )
{
if ( p->nNegative[0]++ == 0 )
{
p->nNegative[1] = End;
p->nNegative[2] = Beg;
p->nNegative[3] = Wlc_PrsFindLine(p, pStart);
}
}
if ( End < Beg )
{
if ( p->nReverse[0]++ == 0 )
{
p->nReverse[1] = End;
p->nReverse[2] = Beg;
p->nReverse[3] = Wlc_PrsFindLine(p, pStart);
}
}
while ( 1 )
{
char * pName; int XValue, TypeNew;
pStart = Wlc_PrsFindName( pStart, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name in declaration." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is declared more than once.", pName );
iObj = Wlc_ObjAlloc( p->pNtk, Type, Signed, End, Beg );
if ( fIsPo ) Wlc_ObjSetCo( p->pNtk, Wlc_NtkObj(p->pNtk, iObj), 0 );
assert( iObj == NameId );
pStart = Wlc_PrsSkipSpaces( pStart );
if ( pStart[0] == ',' )
{
pStart++;
continue;
}
TypeNew = Wlc_PrsFindDefinition( p, pStart, p->vFanins, &XValue );
if ( TypeNew )
{
Wlc_Obj_t * pObj = Wlc_NtkObj( p->pNtk, iObj );
Wlc_ObjUpdateType( p->pNtk, pObj, TypeNew );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
pObj->fXConst = XValue;
}
break;
}
return 1;
}
int Wlc_PrsDerive( Wlc_Prs_t * p, int fInter )
{
Wlc_Obj_t * pObj;
char * pStart, * pName;
int i;
Wlc_PrsForEachLine( p, pStart, i )
{
startword:
if ( Wlc_PrsStrCmp( pStart, "module" ) )
{
pName = Wlc_PrsStrtok( pStart + strlen("module"), " \r\n\t(,)" );
if ( pName == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read model name." );
if ( Wlc_PrsStrCmp( pName, "CPL_" ) )
{
while ( ++i < Vec_IntSize(p->vStarts) )
{
pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, i));
pStart = strstr( pStart, "endmodule" );
if ( pStart != NULL )
break;
}
continue;
}
if ( Wlc_PrsStrCmp( pName, "table" ) )
{
int Width1 = -1, Width2 = -1;
int v, b, Value, nBits, nInts;
unsigned * pTable;
Vec_Int_t * vValues = Vec_IntAlloc( 256 );
Wlc_PrsForEachLineStart( p, pStart, i, i+1 )
{
if ( Wlc_PrsStrCmp( pStart, "endcase" ) )
break;
pStart = Wlc_PrsFindSymbol( pStart, '\'' );
if ( pStart == NULL )
continue;
Width1 = atoi(pStart-1);
pStart = Wlc_PrsFindSymbol( pStart+2, '\'' );
if ( pStart == NULL )
continue;
Width2 = atoi(pStart-1);
Value = 0;
Abc_TtReadHexNumber( (word *)&Value, pStart+2 );
Vec_IntPush( vValues, Value );
}
nBits = Abc_Base2Log( Vec_IntSize(vValues) );
if ( Vec_IntSize(vValues) != (1 << nBits) )
{
Vec_IntFree( vValues );
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read module \"%s\".", pName );
}
assert( Width1 == nBits );
nInts = Abc_BitWordNum( Width2 * Vec_IntSize(vValues) );
pTable = (unsigned *)Mem_FlexEntryFetch( p->pMemTable, nInts * sizeof(unsigned) );
memset( pTable, 0, nInts * sizeof(unsigned) );
Vec_IntForEachEntry( vValues, Value, v )
for ( b = 0; b < Width2; b++ )
if ( (Value >> b) & 1 )
Abc_InfoSetBit( pTable, v * Width2 + b );
Vec_PtrPush( p->vTables, pTable );
Vec_IntFree( vValues );
continue;
}
if ( p->pNtk != NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Network is already defined." );
p->pNtk = Wlc_NtkAlloc( pName, Vec_IntSize(p->vStarts) );
p->pNtk->pManName = Abc_NamStart( Vec_IntSize(p->vStarts), 20 );
p->pNtk->pMemTable = p->pMemTable; p->pMemTable = NULL;
p->pNtk->vTables = p->vTables; p->vTables = NULL;
while ( (pName = Wlc_PrsStrtok( NULL, "(,)" )) )
{
pName = Wlc_PrsSkipSpaces( pName );
if ( fInter && Wlc_PrsStrCmp( pName, "wire" ) )
return 0;
if ( Wlc_PrsStrCmp( pName, "input" ) || Wlc_PrsStrCmp( pName, "output" ) || Wlc_PrsStrCmp( pName, "wire" ) )
{
if ( !Wlc_PrsReadDeclaration( p, pName ) )
return 0;
}
}
}
else if ( Wlc_PrsStrCmp( pStart, "endmodule" ) )
{
Vec_Int_t * vTemp = Vec_IntStartNatural( Wlc_NtkObjNumMax(p->pNtk) );
Vec_IntAppend( &p->pNtk->vNameIds, vTemp );
Vec_IntFree( vTemp );
if ( p->pNtk->vInits )
{
assert( (Vec_IntSize(&p->pNtk->vFfs) & 1) == 0 );
assert( Vec_IntSize(&p->pNtk->vFfs) == 2 * Vec_IntSize(p->pNtk->vInits) );
Wlc_NtkForEachFf( p->pNtk, pObj, i )
if ( i & 1 )
Wlc_ObjSetCo( p->pNtk, pObj, 1 );
else
Wlc_ObjSetCi( p->pNtk, pObj );
Vec_IntClear( &p->pNtk->vFfs );
p->pNtk->pInits = Wlc_PrsConvertInitValues( p->pNtk );
}
if ( p->pNtk->vArsts && !p->pNtk->fAsyncRst )
{
int i, NameIdArst;
Vec_IntForEachEntry( p->pNtk->vArsts, NameIdArst, i )
{
if ( Wlc_PrsCheckBitConst0(p->pNtk, NameIdArst) )
continue;
p->pNtk->fAsyncRst = 1;
printf( "Detected async reset \"%s\".\n", Abc_NamStr(p->pNtk->pManName, NameIdArst) );
break;
}
}
if ( p->vPoPairs )
{
assert( Vec_StrEntryLast(p->vPoPairs) == 0 );
Vec_StrPush( p->vPoPairs, 0 );
pName = Vec_StrArray(p->vPoPairs);
while ( *pName )
{
Wlc_NtkForEachPo( p->pNtk, pObj, i )
if ( !strcmp(Wlc_ObjName(p->pNtk, Wlc_ObjId(p->pNtk, pObj)), pName) )
{
Vec_IntPush( &p->pNtk->vPoPairs, i );
break;
}
assert( i < Wlc_NtkPoNum(p->pNtk) );
pName += strlen(pName) + 1;
}
assert( Vec_IntSize(&p->pNtk->vPoPairs) % 2 == 0 );
printf( "Finished parsing %d output pairs to be checked for equivalence.\n", Vec_IntSize(&p->pNtk->vPoPairs)/2 );
}
break;
}
else if ( Wlc_PrsStrCmp( pStart, "input" ) || Wlc_PrsStrCmp( pStart, "output" ) || Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" ) )
{
if ( fInter && (Wlc_PrsStrCmp( pStart, "wire" ) || Wlc_PrsStrCmp( pStart, "reg" )) )
return 0;
if ( !Wlc_PrsReadDeclaration( p, pStart ) )
return 0;
}
else if ( Wlc_PrsStrCmp( pStart, "assign" ) )
{
int Type, NameId, fFound, XValue = 0;
if ( fInter )
return 0;
pStart += strlen("assign");
pStart = Wlc_PrsFindName( pStart, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
Type = Wlc_PrsFindDefinition( p, pStart, p->vFanins, &XValue );
if ( Type )
{
pObj = Wlc_NtkObj( p->pNtk, NameId );
Wlc_ObjUpdateType( p->pNtk, pObj, Type );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
pObj->fXConst = XValue;
}
else
return 0;
}
else if ( Wlc_PrsStrCmp( pStart, "table" ) )
{
int NameId, fFound, iTable = atoi( pStart + strlen("table") );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameId );
Vec_IntPush( p->vFanins, iTable );
pStart = Wlc_PrsFindSymbol( pStart, ',' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after assign." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
pObj = Wlc_NtkObj( p->pNtk, NameId );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_TABLE );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( Wlc_PrsStrCmp( pStart, "always" ) )
{
int NameId, NameIdOut = -1, fFound, nValues, fDefaultFound = 0;
if ( fInter )
return 0;
pStart = Wlc_PrsFindWord( pStart, "case", &fFound );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
pStart = Wlc_PrsFindSymbol( pStart+1, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read table." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." );
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameId );
pObj = Wlc_NtkObj( p->pNtk, NameId );
if ( pObj == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find the object in case statement." );
nValues = (1 << Wlc_ObjRange(pObj));
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, ':' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find colon in the case statement." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name after case." );
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
pStart = Wlc_PrsFindSymbol( pStart, '=' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot find equality in the case statement." );
pStart = Wlc_PrsSkipSpaces( pStart+1 );
pStart = Wlc_PrsReadName( p, pStart, p->vFanins );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside case statement." );
if ( fDefaultFound )
{
int EntryLast = Vec_IntEntryLast( p->vFanins );
if (nValues != Vec_IntSize(p->vFanins)-2)
Vec_IntFillExtra( p->vFanins, nValues + 1, EntryLast );
else
Vec_IntPop(p->vFanins);
pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i));
pStart = Wlc_PrsSkipSpaces( pStart );
}
else
{
pStart = Wlc_PrsStr(p, Vec_IntEntry(p->vStarts, ++i));
pStart = Wlc_PrsSkipSpaces( pStart );
if ( Wlc_PrsIsDigit(pStart) )
continue;
if ( Wlc_PrsStrCmp( pStart, "default" ) )
{
fDefaultFound = 1;
continue;
}
}
pStart = Wlc_PrsFindWord( pStart, "endcase", &fFound );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
pStart = Wlc_PrsFindWord( pStart, "end", &fFound );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read case statement." );
pStart = Wlc_PrsSkipSpaces( pStart );
break;
}
if ( nValues < Vec_IntSize(p->vFanins) - 1 ) {
printf( "Warning: The number of values in the case statement is wrong.\n" );
Vec_IntShrink(p->vFanins,nValues+1);
}
else if ( nValues > Vec_IntSize(p->vFanins) - 1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "The number of values in the case statement is wrong.", pName );
if ( Wlc_ObjRange(pObj) == 1 )
{
printf( "Warning: Case-statement with 1-bit control is treated as a 2:1 MUX (correct for unsigned signals only).\n" );
}
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_MUX );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
goto startword;
}
else if ( Wlc_PrsStrCmp( pStart, "CPL_FF" ) )
{
int NameId = -1, NameIdIn = -1, NameIdOut = -1, fFound, nBits = 1, fFlopIn, fFlopOut;
pStart += strlen("CPL_FF");
if ( pStart[0] == '#' )
nBits = atoi(pStart+1);
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !p->pNtk->fAsyncRst && !strncmp(pStart, "arst", 4) && pStart[4] != 'v' )
{
int NameIdArst;
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( Wlc_PrsIsDigit(pStart) )
{
int Range, Signed, XValue;
Vec_Int_t * vFanins = Vec_IntAlloc( 100 );
pStart = Wlc_PrsReadConstant( p, pStart, vFanins, &Range, &Signed, &XValue );
if ( pStart && Vec_IntSize(vFanins) == 1 && Vec_IntEntry(vFanins, 0) == 0 )
{
Vec_IntFree( vFanins );
continue;
}
printf( "Detected async reset.\n" );
p->pNtk->fAsyncRst = 1;
Vec_IntFree( vFanins );
continue;
}
pStart = Wlc_PrsFindName( pStart, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
NameIdArst = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( p->pNtk->vArsts == NULL )
p->pNtk->vArsts = Vec_IntAlloc( 100 );
Vec_IntPushUnique( p->pNtk->vArsts, NameIdArst );
continue;
}
if ( pStart[0] != 'd' && (pStart[0] != 'q' || pStart[1] == 'b') && strncmp(pStart, "arstval", 7) )
continue;
fFlopIn = (pStart[0] == 'd');
fFlopOut = (pStart[0] == 'q');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameIdIn = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopOut )
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameIdIn == -1 || NameIdOut == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FO );
Vec_IntPush( &p->pNtk->vFfs, NameIdOut );
pObj = Wlc_NtkObj( p->pNtk, NameIdIn );
Vec_IntPush( &p->pNtk->vFfs, NameIdIn );
if ( NameId == -1 )
printf( "Initial value of flop \"%s\" is not specified. Zero is assumed.\n", Abc_NamStr(p->pNtk->pManName, NameIdOut) );
else
{
pObj = Wlc_NtkObj( p->pNtk, NameId );
if ( nBits != Wlc_ObjRange(pObj) )
printf( "Warning! Flop init signal \"%s\" bit-width (%d) is different from the flop declaration (%d)\n", Abc_NamStr(p->pNtk->pManName, NameId), Wlc_ObjRange(pObj), nBits );
}
if ( p->pNtk->vInits == NULL )
p->pNtk->vInits = Vec_IntAlloc( 100 );
Vec_IntPush( p->pNtk->vInits, NameId > 0 ? NameId : -nBits );
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFFRSE" ) )
{
int NameId[10] = {0}, fFound, fFlopIn, fFlopClk, fFlopRst, fFlopSet, fFlopEna, fFlopAsync, fFlopSre, fFlopInit, fFlopOut;
pStart += strlen("ABC_DFFRSE");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
fFlopIn = (pStart[0] == 'd');
fFlopClk = (pStart[0] == 'c');
fFlopRst = (pStart[0] == 'r');
fFlopSet = (pStart[0] == 's' && pStart[1] == 'e');
fFlopEna = (pStart[0] == 'e');
fFlopAsync = (pStart[0] == 'a');
fFlopSre = (pStart[0] == 's' && pStart[1] == 'r');
fFlopInit = (pStart[0] == 'i');
fFlopOut = (pStart[0] == 'q');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameId[0] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopClk )
NameId[1] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopRst )
NameId[2] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopSet )
NameId[3] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopEna )
NameId[4] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopAsync )
NameId[5] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopSre )
NameId[6] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopInit )
NameId[7] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopOut )
NameId[8] = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
assert( 0 );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameId[0] == -1 || NameId[7] == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
pObj = Wlc_NtkObj( p->pNtk, NameId[8] );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FF );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameId[0] );
Vec_IntPush( p->vFanins, NameId[1] );
Vec_IntPush( p->vFanins, NameId[2] );
Vec_IntPush( p->vFanins, NameId[3] );
Vec_IntPush( p->vFanins, NameId[4] );
Vec_IntPush( p->vFanins, NameId[5] );
Vec_IntPush( p->vFanins, NameId[6] );
Vec_IntPush( p->vFanins, NameId[7] );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_DFF" ) )
{
int NameId = -1, NameIdIn = -1, NameIdOut = -1, fFound, nBits = 1, fFlopIn, fFlopOut;
pStart += strlen("ABC_DFF");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
fFlopIn = (pStart[0] == 'd');
fFlopOut = (pStart[0] == 'q');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
if ( fFlopIn )
NameIdIn = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fFlopOut )
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameIdIn == -1 || NameIdOut == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of flop input or flop output is missing." );
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_FO );
Vec_IntPush( &p->pNtk->vFfs, NameIdOut );
nBits = Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdOut));
pObj = Wlc_NtkObj( p->pNtk, NameIdIn );
Vec_IntPush( &p->pNtk->vFfs, NameIdIn );
if ( Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdIn)) != nBits )
printf( "Warning! Flop input \"%s\" bit-width (%d) is different from that of flop output (%d)\n",
Abc_NamStr(p->pNtk->pManName, NameId), Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdIn)), nBits );
if ( NameId == -1 )
printf( "Initial value of flop \"%s\" is not specified. Zero is assumed.\n", Abc_NamStr(p->pNtk->pManName, NameIdOut) );
else
{
if ( Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameId)) != nBits )
printf( "Warning! Flop init signal \"%s\" bit-width (%d) is different from that of flop output (%d)\n",
Abc_NamStr(p->pNtk->pManName, NameId), Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameId)), nBits );
}
if ( p->pNtk->vInits == NULL )
p->pNtk->vInits = Vec_IntAlloc( 100 );
Vec_IntPush( p->pNtk->vInits, NameId > 0 ? NameId : -Wlc_ObjRange(Wlc_NtkObj(p->pNtk, NameIdOut)) );
p->pNtk->fEasyFfs = 1;
}
else if ( Wlc_PrsStrCmp( pStart, "CPL_MEM_" ) )
{
int * pNameId = NULL, NameOutput, NameMi = -1, NameMo = -1, NameAddr = -1, NameDi = -1, NameDo = -1, fFound, fRead = 1;
pStart += strlen("CPL_MEM_");
if ( pStart[0] == 'W' )
fRead = 0;
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !strncmp(pStart, "mem_data_in", 11) )
pNameId = &NameMi;
else if ( !strncmp(pStart, "data_in", 7) )
pNameId = &NameDi;
else if ( !strncmp(pStart, "data_out", 8) )
pNameId = fRead ? &NameDo : &NameMo;
else if ( !strncmp(pStart, "addr_in", 7) )
pNameId = &NameAddr;
else
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name of the input/output port." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
*pNameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( fRead && (NameMi == -1 || NameAddr == -1 || NameDo == -1) )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of read port is missing." );
if ( !fRead && (NameMi == -1 || NameAddr == -1 || NameDi == -1 || NameMo == -1) )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of write port is missing." );
NameOutput = fRead ? NameDo : NameMo;
pObj = Wlc_NtkObj( p->pNtk, NameOutput );
Wlc_ObjUpdateType( p->pNtk, pObj, fRead ? WLC_OBJ_READ : WLC_OBJ_WRITE );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameMi );
Vec_IntPush( p->vFanins, NameAddr );
if ( !fRead )
Vec_IntPush( p->vFanins, NameDi );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_READ" ) )
{
int * pNameId = NULL, NameMemIn = -1, NameData = -1, NameAddr = -1, fFound;
pStart += strlen("ABC_READ");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !strncmp(pStart, "mem_in", 6) )
pNameId = &NameMemIn;
else if ( !strncmp(pStart, "addr", 4) )
pNameId = &NameAddr;
else if ( !strncmp(pStart, "data", 4) )
pNameId = &NameData;
else
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name of the input/output port." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
*pNameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameMemIn == -1 || NameAddr == -1 || NameData == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of read port is missing." );
pObj = Wlc_NtkObj( p->pNtk, NameData );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_READ );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameMemIn );
Vec_IntPush( p->vFanins, NameAddr );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
p->pNtk->fMemPorts = 1;
}
else if ( Wlc_PrsStrCmp( pStart, "ABC_WRITE" ) )
{
int * pNameId = NULL, NameMemIn = -1, NameMemOut = -1, NameData = -1, NameAddr = -1, fFound;
pStart += strlen("ABC_WRITE");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( !strncmp(pStart, "mem_in", 6) )
pNameId = &NameMemIn;
else if ( !strncmp(pStart, "mem_out", 7) )
pNameId = &NameMemOut;
else if ( !strncmp(pStart, "data", 4) )
pNameId = &NameData;
else if ( !strncmp(pStart, "addr", 4) )
pNameId = &NameAddr;
else
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name of the input/output port." );
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the flop description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside flop description." );
*pNameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameMemIn == -1 || NameAddr == -1 || NameData == -1 || NameMemOut == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name of one of signals of write port is missing." );
pObj = Wlc_NtkObj( p->pNtk, NameMemOut );
Wlc_ObjUpdateType( p->pNtk, pObj, WLC_OBJ_WRITE );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameMemIn );
Vec_IntPush( p->vFanins, NameAddr );
Vec_IntPush( p->vFanins, NameData );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
p->pNtk->fMemPorts = 1;
}
else if ( Wlc_PrsStrCmp( pStart, "CPL_RROT" ) || Wlc_PrsStrCmp( pStart, "CPL_LROT" ) )
{
int right_rotation = Wlc_PrsStrCmp( pStart, "CPL_RROT" );
int NameId = -1, NameIdOut = -1, NameIdInD = -1, NameIdInS = -1, fFound, fRotInD, fRotInS, fRotOut;
pStart += strlen("CPL_RROT");
while ( 1 )
{
pStart = Wlc_PrsFindSymbol( pStart, '.' );
if ( pStart == NULL )
break;
pStart = Wlc_PrsSkipSpaces( pStart+1 );
if ( pStart[0] != 'o' && pStart[0] != 'd' && pStart[0] != 's')
continue;
fRotInD = (pStart[0] == 'd');
fRotInS = (pStart[0] == 's');
fRotOut = (pStart[0] == 'o');
pStart = Wlc_PrsFindSymbol( pStart, '(' );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read opening parenthesis in the rotation description." );
pStart = Wlc_PrsFindName( pStart+1, &pName );
if ( pStart == NULL )
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read name inside rotation description." );
if ( fRotInD )
NameIdInD = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fRotInS )
NameIdInS = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else if ( fRotOut )
NameIdOut = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
else
NameId = Abc_NamStrFindOrAdd( p->pNtk->pManName, pName, &fFound );
if ( !fFound )
return Wlc_PrsWriteErrorMessage( p, pStart, "Name %s is not declared.", pName );
}
if ( NameIdOut == -1 || NameIdInD == -1 || NameIdInS == -1 )
return Wlc_PrsWriteErrorMessage( p, pStart, "Some fields of CPL_ROT are missing." );
pObj = Wlc_NtkObj( p->pNtk, NameIdOut );
Wlc_ObjUpdateType( p->pNtk, pObj, right_rotation ? WLC_OBJ_ROTATE_R : WLC_OBJ_ROTATE_L );
Vec_IntClear( p->vFanins );
Vec_IntPush( p->vFanins, NameIdInD );
Vec_IntPush( p->vFanins, NameIdInS );
Wlc_ObjAddFanins( p->pNtk, pObj, p->vFanins );
}
else if ( pStart[0] == '(' && pStart[1] == '*' ) {
while ( *pStart++ != ')' );
pStart = Wlc_PrsSkipSpaces( pStart );
goto startword;
}
else if ( pStart[0] != '`' )
{
int iLine = Wlc_PrsFindLine(p, pStart);
pStart = Wlc_PrsFindName( pStart, &pName );
return Wlc_PrsWriteErrorMessage( p, pStart, "Cannot read line %d beginning with %s.", iLine, (!pName || !pName[0]) ? "\"?\"" : pName );
}
}
if ( p->nNonZero[0] )
{
printf( "Warning: Input file contains %d objects with non-zero-based ranges.\n", p->nNonZero[0] );
printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nNonZero[1], p->nNonZero[2], p->nNonZero[3] );
}
if ( p->nNegative[0] )
{
printf( "Warning: Input file contains %d objects with negative ranges.\n", p->nNegative[0] );
printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nNegative[1], p->nNegative[2], p->nNegative[3] );
}
if ( p->nReverse[0] )
{
printf( "Warning: Input file contains %d objects with reversed ranges.\n", p->nReverse[0] );
printf( "For example, signal with range [%d:%d] is declared in line %d.\n", p->nReverse[1], p->nReverse[2], p->nReverse[3] );
}
return 1;
}
Wlc_Ntk_t * Wlc_ReadVer( char * pFileName, char * pStr, int fInter )
{
Wlc_Prs_t * p;
Wlc_Ntk_t * pNtk = NULL;
assert( (pFileName == NULL) != (pStr == NULL) );
p = Wlc_PrsStart( pFileName, pStr );
if ( p == NULL )
return NULL;
if ( !Wlc_PrsPrepare( p ) )
goto finish;
if ( !Wlc_PrsDerive( p, fInter ) )
{
if ( fInter )
{
printf( "Finished deriving interface for module \"%s\".\n", p->pNtk->pName );
pNtk = p->pNtk; p->pNtk = NULL;
pNtk->pSpec = Abc_UtilStrsav( pFileName );
if ( Vec_IntSize(&pNtk->vNameIds) == 0 )
{
Vec_Int_t * vTemp = Vec_IntStartNatural( Wlc_NtkObjNumMax(pNtk) );
pNtk->vNameIds = *vTemp, Vec_IntZero(vTemp);
Vec_IntFree( vTemp );
}
return pNtk;
}
goto finish;
}
if ( p->pNtk )
{
Wlc_Obj_t * pObj; int i;
Wlc_NtkForEachObj( p->pNtk, pObj, i )
if ( pObj->Type == WLC_OBJ_FF )
Vec_IntPush( &p->pNtk->vFfs2, Wlc_ObjId(p->pNtk, pObj) );
pNtk = Wlc_NtkDupDfs( p->pNtk, 0, 1 );
pNtk->pSpec = Abc_UtilStrsav( pFileName );
}
finish:
Wlc_PrsPrintErrorMessage( p );
Wlc_PrsStop( p );
return pNtk;
}
void Io_ReadWordTest( char * pFileName )
{
Gia_Man_t * pNew;
Wlc_Ntk_t * pNtk = Wlc_ReadVer( pFileName, NULL, 0 );
if ( pNtk == NULL )
return;
Wlc_WriteVer( pNtk, "test.v", 0, 0 );
pNew = Wlc_NtkBitBlast( pNtk, NULL );
Gia_AigerWrite( pNew, "test.aig", 0, 0, 0 );
Gia_ManStop( pNew );
Wlc_NtkFree( pNtk );
}
ABC_NAMESPACE_IMPL_END