abc/src/base/ver/verCore.c

1232 lines
39 KiB
C

/**CFile****************************************************************
FileName [verCore.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Verilog parser.]
Synopsis [Parses several flavors of structural Verilog.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - August 19, 2006.]
Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ver.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// types of verilog signals
typedef enum {
VER_SIG_NONE = 0,
VER_SIG_INPUT,
VER_SIG_OUTPUT,
VER_SIG_INOUT,
VER_SIG_REG,
VER_SIG_WIRE
} Ver_SignalType_t;
// types of verilog gates
typedef enum {
VER_GATE_AND = 0,
VER_GATE_OR,
VER_GATE_XOR,
VER_GATE_BUF,
VER_GATE_NAND,
VER_GATE_NOR,
VER_GATE_XNOR,
VER_GATE_NOT
} Ver_GateType_t;
static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib );
static void Ver_ParseStop( Ver_Man_t * p );
static void Ver_ParseFreeData( Ver_Man_t * p );
static void Ver_ParseInternal( Ver_Man_t * p );
static int Ver_ParseModule( Ver_Man_t * p );
static int Ver_ParseSignal( Ver_Man_t * p, Ver_SignalType_t SigType );
static int Ver_ParseAssign( Ver_Man_t * p );
static int Ver_ParseAlways( Ver_Man_t * p );
static int Ver_ParseInitial( Ver_Man_t * p );
static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtkGate );
static int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType );
static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName );
static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName );
static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO );
static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [File parser.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan )
{
Ver_Man_t * p;
Abc_Lib_t * pDesign;
// start the parser
p = Ver_ParseStart( pFileName, pGateLib );
p->fCheck = fCheck;
p->fUseMemMan = fUseMemMan;
// parse the file
Ver_ParseInternal( p );
// save the result
pDesign = p->pDesign;
p->pDesign = NULL;
// stop the parser
Ver_ParseStop( p );
return pDesign;
}
/**Function*************************************************************
Synopsis [Start parser.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib )
{
Ver_Man_t * p;
p = ALLOC( Ver_Man_t, 1 );
memset( p, 0, sizeof(Ver_Man_t) );
p->pFileName = pFileName;
p->pReader = Ver_StreamAlloc( pFileName );
p->Output = stdout;
p->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(p->pReader) );
p->vNames = Vec_PtrAlloc( 100 );
p->vStackFn = Vec_PtrAlloc( 100 );
p->vStackOp = Vec_IntAlloc( 100 );
// create the design library and assign the technology library
p->pDesign = Abc_LibCreate( pFileName );
p->pDesign->pLibrary = pGateLib;
return p;
}
/**Function*************************************************************
Synopsis [Stop parser.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParseStop( Ver_Man_t * p )
{
assert( p->pNtkCur == NULL );
Ver_StreamFree( p->pReader );
Extra_ProgressBarStop( p->pProgress );
Vec_PtrFree( p->vNames );
Vec_PtrFree( p->vStackFn );
Vec_IntFree( p->vStackOp );
free( p );
}
/**Function*************************************************************
Synopsis [File parser.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParseInternal( Ver_Man_t * pMan )
{
char * pToken;
while ( 1 )
{
// get the next token
pToken = Ver_ParseGetName( pMan );
if ( pToken == NULL )
break;
if ( strcmp( pToken, "module" ) )
{
sprintf( pMan->sError, "Cannot read \"module\" directive." );
Ver_ParsePrintErrorMessage( pMan );
return;
}
// parse the module
if ( !Ver_ParseModule( pMan ) )
return;
// check the network for correctness
if ( pMan->fCheck && !Abc_NtkCheckRead( pMan->pNtkCur ) )
{
pMan->fTopLevel = 1;
sprintf( pMan->sError, "The network check has failed.", pMan->pNtkCur->pName );
Ver_ParsePrintErrorMessage( pMan );
return;
}
// add the module to the hash table
if ( st_is_member( pMan->pDesign->tModules, pMan->pNtkCur->pName ) )
{
pMan->fTopLevel = 1;
sprintf( pMan->sError, "Module \"%s\" is defined more than once.", pMan->pNtkCur->pName );
Ver_ParsePrintErrorMessage( pMan );
return;
}
Vec_PtrPush( pMan->pDesign->vModules, pMan->pNtkCur );
st_insert( pMan->pDesign->tModules, pMan->pNtkCur->pName, (char *)pMan->pNtkCur );
pMan->pNtkCur = NULL;
}
}
/**Function*************************************************************
Synopsis [File parser.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParseFreeData( Ver_Man_t * p )
{
if ( p->pNtkCur )
{
p->pNtkCur->pManFunc = NULL;
Abc_NtkDelete( p->pNtkCur );
p->pNtkCur = NULL;
}
if ( p->pDesign )
{
Abc_LibFree( p->pDesign, NULL );
p->pDesign = NULL;
}
}
/**Function*************************************************************
Synopsis [Prints the error message including the file name and line number.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ver_ParsePrintErrorMessage( Ver_Man_t * p )
{
p->fError = 1;
if ( p->fTopLevel ) // the line number is not given
fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError );
else // print the error message with the line number
fprintf( p->Output, "%s (line %d): %s\n",
p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError );
// free the data
Ver_ParseFreeData( p );
}
/**Function*************************************************************
Synopsis [Parses one Verilog module.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseModule( Ver_Man_t * pMan )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk, * pNtkTemp;
Abc_Obj_t * pNet;
char * pWord, Symbol;
int RetValue;
// start the current network
assert( pMan->pNtkCur == NULL );
pNtk = pMan->pNtkCur = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan );
pNtk->ntkFunc = ABC_FUNC_AIG;
pNtk->pManFunc = pMan->pDesign->pManFunc;
// get the network name
pWord = Ver_ParseGetName( pMan );
pNtk->pName = Extra_UtilStrsav( pWord );
pNtk->pSpec = NULL;
// create constant nets
Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
// make sure we stopped at the opening paranthesis
if ( Ver_StreamPopChar(p) != '(' )
{
sprintf( pMan->sError, "Cannot find \"(\" after \"module\".", pNtk->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// skip to the end of parantheses
do {
if ( Ver_ParseGetName( pMan ) == NULL )
return 0;
Symbol = Ver_StreamPopChar(p);
} while ( Symbol == ',' );
assert( Symbol == ')' );
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
Symbol = Ver_StreamPopChar(p);
assert( Symbol == ';' );
// parse the inputs/outputs/registers/wires/inouts
while ( 1 )
{
Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
if ( !strcmp( pWord, "input" ) )
RetValue = Ver_ParseSignal( pMan, VER_SIG_INPUT );
else if ( !strcmp( pWord, "output" ) )
RetValue = Ver_ParseSignal( pMan, VER_SIG_OUTPUT );
else if ( !strcmp( pWord, "reg" ) )
RetValue = Ver_ParseSignal( pMan, VER_SIG_REG );
else if ( !strcmp( pWord, "wire" ) )
RetValue = Ver_ParseSignal( pMan, VER_SIG_WIRE );
else if ( !strcmp( pWord, "inout" ) )
RetValue = Ver_ParseSignal( pMan, VER_SIG_INOUT );
else
break;
if ( RetValue == 0 )
return 0;
}
// parse the remaining statements
while ( 1 )
{
Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL );
if ( !strcmp( pWord, "and" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_AND );
else if ( !strcmp( pWord, "or" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_OR );
else if ( !strcmp( pWord, "xor" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XOR );
else if ( !strcmp( pWord, "buf" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_BUF );
else if ( !strcmp( pWord, "nand" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NAND );
else if ( !strcmp( pWord, "nor" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOR );
else if ( !strcmp( pWord, "xnor" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_XNOR );
else if ( !strcmp( pWord, "not" ) )
RetValue = Ver_ParseGateStandard( pMan, VER_GATE_NOT );
else if ( !strcmp( pWord, "assign" ) )
RetValue = Ver_ParseAssign( pMan );
else if ( !strcmp( pWord, "always" ) )
RetValue = Ver_ParseAlways( pMan );
else if ( !strcmp( pWord, "initial" ) )
RetValue = Ver_ParseInitial( pMan );
else if ( !strcmp( pWord, "endmodule" ) )
break;
else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library
RetValue = Ver_ParseGate( pMan, pNtkTemp );
else if ( pMan->pDesign && st_lookup(pMan->pDesign->tModules, pWord, (char**)&pNtkTemp) ) // current design
RetValue = Ver_ParseGate( pMan, pNtkTemp );
else
{
printf( "Cannot find \"%s\".\n", pWord );
Ver_StreamSkipToChars( p, ";" );
Ver_StreamPopChar(p);
// sprintf( pMan->sError, "Cannot find \"%s\" in the library.", pWord );
// Ver_ParsePrintErrorMessage( pMan );
// return 0;
}
if ( RetValue == 0 )
return 0;
// skip the comments
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
// get new word
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
}
// check if constant 0 net is used
pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b0" );
if ( Abc_ObjFanoutNum(pNet) == 0 )
Abc_NtkDeleteObj(pNet);
else
Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) );
// check if constant 1 net is used
pNet = Abc_NtkFindOrCreateNet( pNtk, "1\'b1" );
if ( Abc_ObjFanoutNum(pNet) == 0 )
Abc_NtkDeleteObj(pNet);
else
Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) );
// check the functionality to blackbox if insides are not defined
if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 )
{
pNtk->ntkFunc = ABC_FUNC_BLACKBOX;
pNtk->pManFunc = NULL;
}
// fix the dangling nets
Abc_NtkFinalizeRead( pNtk );
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseSignal( Ver_Man_t * pMan, Ver_SignalType_t SigType )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk = pMan->pNtkCur;
char Buffer[1000];
int Lower, Upper, i;
char * pWord;
char Symbol;
while ( 1 )
{
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
if ( pWord[0] == '[' && !pMan->fNameLast )
{
Lower = atoi( pWord + 1 );
// find the splitter
while ( *pWord && *pWord != ':' && *pWord != ']' )
pWord++;
if ( *pWord == 0 )
{
sprintf( pMan->sError, "Cannot find closing bracket in this line." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
if ( *pWord == ']' )
Upper = Lower;
else
{
Upper = atoi( pWord + 1 );
if ( Lower > Upper )
i = Lower, Lower = Upper, Upper = i;
// find the closing paranthesis
while ( *pWord && *pWord != ']' )
pWord++;
if ( *pWord == 0 )
{
sprintf( pMan->sError, "Cannot find closing bracket in this line." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
assert( *pWord == ']' );
}
// check the case of no space between bracket and the next word
if ( *(pWord+1) != 0 )
pWord++;
else
{
// get the signal name
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
}
for ( i = Lower; i <= Upper; i++ )
{
sprintf( Buffer, "%s[%d]", pWord, i );
if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePi( pNtk, Buffer );
if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePo( pNtk, Buffer );
if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
Abc_NtkFindOrCreateNet( pNtk, Buffer );
}
}
else
{
if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePi( pNtk, pWord );
if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT )
Ver_ParseCreatePo( pNtk, pWord );
if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG )
Abc_NtkFindOrCreateNet( pNtk, pWord );
}
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ',' )
continue;
if ( Symbol == ';' )
return 1;
break;
}
sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseAssign( Ver_Man_t * pMan )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk = pMan->pNtkCur;
Abc_Obj_t * pNode, * pNet;
char * pWord, * pName, * pEquation;
Hop_Obj_t * pFunc;
char Symbol;
int i, Length, fReduction;
// if ( Ver_StreamGetLineNumber(p) == 2756 )
// {
// int x = 0;
// }
// convert from the mapped netlist into the BDD netlist
if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX )
{
pNtk->ntkFunc = ABC_FUNC_AIG;
assert( pNtk->pManFunc == NULL );
pNtk->pManFunc = pMan->pDesign->pManFunc;
}
else if ( pNtk->ntkFunc != ABC_FUNC_AIG )
{
sprintf( pMan->sError, "The network %s appears to mapped gates and assign statements. Currently such network are not allowed. One way to fix this problem is to replace assigns by buffers from the library.", pMan->pNtkCur );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
while ( 1 )
{
// get the name of the output signal
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// consider the case of reduction operations
fReduction = 0;
if ( pWord[0] == '{' && !pMan->fNameLast )
fReduction = 1;
if ( fReduction )
{
pWord++;
pWord[strlen(pWord)-1] = 0;
assert( pWord[0] != '\\' );
}
// get the fanout net
pNet = Abc_NtkFindNet( pNtk, pWord );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// get the equality sign
if ( Ver_StreamPopChar(p) != '=' )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// skip the comments
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
// get the second name
if ( fReduction )
pEquation = Ver_StreamGetWord( p, ";" );
else
pEquation = Ver_StreamGetWord( p, ",;" );
if ( pEquation == NULL )
{
sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// parse the formula
if ( fReduction )
pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError );
else
pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError );
if ( pFunc == NULL )
{
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// create the node with the given inputs
pNode = Abc_NtkCreateNode( pMan->pNtkCur );
pNode->pData = pFunc;
Abc_ObjAddFanin( pNet, pNode );
// connect to fanin nets
for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ )
{
// get the name of this signal
Length = (int)Vec_PtrEntry( pMan->vNames, 2*i );
pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 );
pName[Length] = 0;
// find the corresponding net
pNet = Abc_NtkFindNet( pNtk, pName );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %d is not defined).", pWord, pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Abc_ObjAddFanin( pNode, pNet );
}
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ',' )
continue;
if ( Symbol == ';' )
return 1;
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseAlways( Ver_Man_t * pMan )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk = pMan->pNtkCur;
Abc_Obj_t * pNet, * pNet2;
int fStopAfterOne;
char * pWord, * pWord2;
char Symbol;
// parse the directive
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
if ( pWord[0] == '@' )
{
Ver_StreamSkipToChars( p, ")" );
Ver_StreamPopChar(p);
// parse the directive
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
}
// decide how many statements to parse
fStopAfterOne = 0;
if ( strcmp( pWord, "begin" ) )
fStopAfterOne = 1;
// iterate over the initial states
while ( 1 )
{
if ( !fStopAfterOne )
{
// get the name of the output signal
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// look for the end of directive
if ( !strcmp( pWord, "end" ) )
break;
}
// get the fanout net
pNet = Abc_NtkFindNet( pNtk, pWord );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// get the equality sign
Symbol = Ver_StreamPopChar(p);
if ( Symbol != '<' && Symbol != '=' )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
if ( Symbol == '<' )
Ver_StreamPopChar(p);
// skip the comments
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
// get the second name
pWord2 = Ver_ParseGetName( pMan );
if ( pWord2 == NULL )
return 0;
// check if the name is complemented
if ( pWord2[0] == '~' )
{
pNet2 = Abc_NtkFindNet( pNtk, pWord2+1 );
pNet2 = Ver_ParseCreateInv( pNtk, pNet2 );
}
else
pNet2 = Abc_NtkFindNet( pNtk, pWord2 );
if ( pNet2 == NULL )
{
sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// create the latch
Ver_ParseCreateLatch( pNtk, pNet2, pNet );
// remove the last symbol
Symbol = Ver_StreamPopChar(p);
assert( Symbol == ';' );
// quit if only one directive
if ( fStopAfterOne )
break;
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseInitial( Ver_Man_t * pMan )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk = pMan->pNtkCur;
Abc_Obj_t * pNode, * pNet;
int fStopAfterOne;
char * pWord, * pEquation;
char Symbol;
// parse the directive
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// decide how many statements to parse
fStopAfterOne = 0;
if ( strcmp( pWord, "begin" ) )
fStopAfterOne = 1;
// iterate over the initial states
while ( 1 )
{
if ( !fStopAfterOne )
{
// get the name of the output signal
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// look for the end of directive
if ( !strcmp( pWord, "end" ) )
break;
}
// get the fanout net
pNet = Abc_NtkFindNet( pNtk, pWord );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// get the equality sign
Symbol = Ver_StreamPopChar(p);
if ( Symbol != '<' && Symbol != '=' )
{
sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
if ( Symbol == '<' )
Ver_StreamPopChar(p);
// skip the comments
if ( !Ver_ParseSkipComments( pMan ) )
return 0;
// get the second name
pEquation = Ver_StreamGetWord( p, ";" );
if ( pEquation == NULL )
return 0;
// find the corresponding latch
if ( Abc_ObjFaninNum(pNet) == 0 )
{
sprintf( pMan->sError, "Cannot find the latch to assign the initial value." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet));
assert( Abc_ObjIsLatch(pNode) );
// set the initial state
if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") )
Abc_LatchSetInit0( pNode );
else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") )
Abc_LatchSetInit1( pNode );
// else if ( !strcmp(pEquation, "2") )
// Abc_LatchSetInitDc( pNode );
else
{
sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// remove the last symbol
Symbol = Ver_StreamPopChar(p);
assert( Symbol == ';' );
// quit if only one directive
if ( fStopAfterOne )
break;
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtkGate )
{
Ver_Stream_t * p = pMan->pReader;
Abc_Ntk_t * pNtk = pMan->pNtkCur;
Abc_Obj_t * pNetFormal, * pNetActual;
Abc_Obj_t * pObj, * pNode, * pTerm;
char * pWord, Symbol, * pGateName;
int i, fCompl, fComplUsed = 0;
unsigned * pPolarity;
// clean the PI/PO pointers
Abc_NtkForEachPi( pNtkGate, pObj, i )
pObj->pCopy = NULL;
Abc_NtkForEachPo( pNtkGate, pObj, i )
pObj->pCopy = NULL;
// parse the directive and set the pointers to the PIs/POs of the gate
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// this is gate name - throw it away
pGateName = pWord;
if ( Ver_StreamPopChar(p) != '(' )
{
sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// parse pairs of formal/actural inputs
while ( 1 )
{
// process one pair of formal/actual parameters
if ( Ver_StreamPopChar(p) != '.' )
{
sprintf( pMan->sError, "Cannot parse gate %s (expected .).", pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// parse the formal name
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// get the formal net
if ( Abc_NtkIsNetlist(pNtkGate) )
pNetFormal = Abc_NtkFindNet( pNtkGate, pWord );
else // if ( Abc_NtkIsStrash(pNtkGate) )
assert( 0 );
if ( pNetFormal == NULL )
{
sprintf( pMan->sError, "Formal net is missing in gate %s.", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// open the paranthesis
if ( Ver_StreamPopChar(p) != '(' )
{
sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// parse the actual name
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// check if the name is complemented
fCompl = (pWord[0] == '~');
if ( fCompl )
{
fComplUsed = 1;
pWord++;
if ( pMan->pNtkCur->pData == NULL )
pMan->pNtkCur->pData = Extra_MmFlexStart();
}
// get the actual net
pNetActual = Abc_NtkFindNet( pMan->pNtkCur, pWord );
if ( pNetActual == NULL )
{
sprintf( pMan->sError, "Actual net is missing in gate %s.", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// close the paranthesis
if ( Ver_StreamPopChar(p) != ')' )
{
sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// process the pair
if ( Abc_ObjFaninNum(pNetFormal) > 0 && Abc_ObjIsPi(Abc_ObjFanin0Ntk(pNetFormal)) ) // PI net (with polarity!)
Abc_ObjFanin0Ntk(pNetFormal)->pCopy = Abc_ObjNotCond( pNetActual, fCompl );
else if ( Abc_ObjFanoutNum(pNetFormal) > 0 && Abc_ObjIsPo(Abc_ObjFanout0Ntk(pNetFormal)) ) // P0 net
{
assert( fCompl == 0 );
Abc_ObjFanout0Ntk(pNetFormal)->pCopy = pNetActual; // Abc_ObjNotCond( pNetActual, fCompl );
}
else
{
sprintf( pMan->sError, "Cannot match formal net %s with PI or PO of the gate %s.", pWord, pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// check if it is the end of gate
Ver_ParseSkipComments( pMan );
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ')' )
break;
// skip comma
if ( Symbol != ',' )
{
sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
}
// check if it is the end of gate
Ver_ParseSkipComments( pMan );
if ( Ver_StreamPopChar(p) != ';' )
{
sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// make sure each input net is driven
Abc_NtkForEachPi( pNtkGate, pObj, i )
if ( pObj->pCopy == NULL )
{
sprintf( pMan->sError, "Formal input %s of gate %s has no actual input.", Abc_ObjName(Abc_ObjFanout0(pObj)), pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
/*
// make sure each output net is driving something
Abc_NtkForEachPo( pNtkGate, pObj, i )
if ( pObj->pCopy == NULL )
{
sprintf( pMan->sError, "Formal output %s of gate %s has no actual output.", Abc_ObjName(Abc_ObjFanin0(pObj)), pNtkGate->pName );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
*/
// allocate memory to remember the phase
pPolarity = NULL;
if ( fComplUsed )
{
int nBytes = 4 * Abc_BitWordNum( Abc_NtkPiNum(pNtkGate) );
pPolarity = (unsigned *)Extra_MmFlexEntryFetch( pMan->pNtkCur->pData, nBytes );
memset( pPolarity, 0, nBytes );
}
// create box to represent this gate
if ( Abc_NtkHasBlackbox(pNtkGate) )
pNode = Abc_NtkCreateBlackbox( pMan->pNtkCur );
else
pNode = Abc_NtkCreateWhitebox( pMan->pNtkCur );
pNode->pNext = (Abc_Obj_t *)pPolarity;
pNode->pData = pNtkGate;
// connect to fanin nets
Abc_NtkForEachPi( pNtkGate, pObj, i )
{
if ( pPolarity && Abc_ObjIsComplement(pObj->pCopy) )
{
Abc_InfoSetBit( pPolarity, i );
pObj->pCopy = Abc_ObjRegular( pObj->pCopy );
}
assert( !Abc_ObjIsComplement(pObj->pCopy) );
// Abc_ObjAddFanin( pNode, pObj->pCopy );
pTerm = Abc_NtkCreateBi( pNtk );
Abc_ObjAddFanin( pTerm, pObj->pCopy );
Abc_ObjAddFanin( pNode, pTerm );
}
// connect to fanout nets
Abc_NtkForEachPo( pNtkGate, pObj, i )
{
if ( pObj->pCopy == NULL )
pObj->pCopy = Abc_NtkFindOrCreateNet(pNtk, NULL);
// Abc_ObjAddFanin( pObj->pCopy, pNode );
pTerm = Abc_NtkCreateBo( pNtk );
Abc_ObjAddFanin( pTerm, pNode );
Abc_ObjAddFanin( pObj->pCopy, pTerm );
}
return 1;
}
/**Function*************************************************************
Synopsis [Parses one directive.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Ver_ParseGateStandard( Ver_Man_t * pMan, Ver_GateType_t GateType )
{
Ver_Stream_t * p = pMan->pReader;
Hop_Man_t * pAig = pMan->pNtkCur->pManFunc;
Abc_Obj_t * pNet, * pNode;
char * pWord, Symbol;
// this is gate name - throw it away
if ( Ver_StreamPopChar(p) != '(' )
{
sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
// create the node
pNode = Abc_NtkCreateNode( pMan->pNtkCur );
// parse pairs of formal/actural inputs
while ( 1 )
{
// parse the output name
pWord = Ver_ParseGetName( pMan );
if ( pWord == NULL )
return 0;
// get the net corresponding to this output
pNet = Abc_NtkFindNet( pMan->pNtkCur, pWord );
if ( pNet == NULL )
{
sprintf( pMan->sError, "Net is missing in gate %s.", pWord );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// if this is the first net, add it as an output
if ( Abc_ObjFanoutNum(pNode) == 0 )
Abc_ObjAddFanin( pNet, pNode );
else
Abc_ObjAddFanin( pNode, pNet );
// check if it is the end of gate
Ver_ParseSkipComments( pMan );
Symbol = Ver_StreamPopChar(p);
if ( Symbol == ')' )
break;
// skip comma
if ( Symbol != ',' )
{
sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
Ver_ParseSkipComments( pMan );
}
if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 )
{
sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// check if it is the end of gate
Ver_ParseSkipComments( pMan );
if ( Ver_StreamPopChar(p) != ';' )
{
sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) );
Ver_ParsePrintErrorMessage( pMan );
return 0;
}
// add logic function
if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND )
pNode->pData = Hop_CreateAnd( pAig, Abc_ObjFaninNum(pNode) );
else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR )
pNode->pData = Hop_CreateOr( pAig, Abc_ObjFaninNum(pNode) );
else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR )
pNode->pData = Hop_CreateExor( pAig, Abc_ObjFaninNum(pNode) );
else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT )
pNode->pData = Hop_CreateAnd( pAig, Abc_ObjFaninNum(pNode) );
if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT )
pNode->pData = Hop_Not( pNode->pData );
return 1;
}
/**Function*************************************************************
Synopsis [Creates PI terminal and net.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName )
{
Abc_Obj_t * pNet, * pTerm;
// get the PI net
pNet = Abc_NtkFindNet( pNtk, pName );
if ( pNet )
printf( "Warning: PI \"%s\" appears twice in the list.\n", pName );
pNet = Abc_NtkFindOrCreateNet( pNtk, pName );
// add the PI node
pTerm = Abc_NtkCreatePi( pNtk );
Abc_ObjAddFanin( pNet, pTerm );
return pTerm;
}
/**Function*************************************************************
Synopsis [Creates PO terminal and net.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName )
{
Abc_Obj_t * pNet, * pTerm;
// get the PO net
pNet = Abc_NtkFindNet( pNtk, pName );
if ( pNet && Abc_ObjFaninNum(pNet) == 0 )
printf( "Warning: PO \"%s\" appears twice in the list.\n", pName );
pNet = Abc_NtkFindOrCreateNet( pNtk, pName );
// add the PO node
pTerm = Abc_NtkCreatePo( pNtk );
Abc_ObjAddFanin( pTerm, pNet );
return pTerm;
}
/**Function*************************************************************
Synopsis [Create a latch with the given input/output.]
Description [By default, the latch value is a don't-care.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO )
{
Abc_Obj_t * pLatch, * pTerm;
// add the BO terminal
pTerm = Abc_NtkCreateBi( pNtk );
Abc_ObjAddFanin( pTerm, pNetLI );
// add the latch box
pLatch = Abc_NtkCreateLatch( pNtk );
Abc_ObjAddFanin( pLatch, pTerm );
// add the BI terminal
pTerm = Abc_NtkCreateBo( pNtk );
Abc_ObjAddFanin( pTerm, pLatch );
// get the LO net
Abc_ObjAddFanin( pNetLO, pTerm );
// set latch name
Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" );
Abc_LatchSetInitDc( pLatch );
return pLatch;
}
/**Function*************************************************************
Synopsis [Creates inverter and returns its net.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
{
Abc_Obj_t * pObj;
pObj = Abc_NtkCreateNodeInv( pNtk, pNet );
pNet = Abc_NtkCreateObj( pNtk, ABC_OBJ_NET );
Abc_ObjAddFanin( pNet, pObj );
return pNet;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////