mirror of https://github.com/YosysHQ/abc.git
1232 lines
39 KiB
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 ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|