2010-11-01 09:35:04 +01:00
/**CFile****************************************************************
FileName [ ioWriteSmv . c ]
SystemName [ ABC : Logic synthesis and verification system . ]
PackageName [ Command processing package . ]
Synopsis [ Procedures to write the network in SMV format . ]
Author [ Satrajit Chatterjee ]
Affiliation [ UC Berkeley ]
Date [ Ver . 1.0 . Started - June 20 , 2005. ]
Revision [ $ Id : ioWriteSmv . c , v 1.00 2005 / 06 / 20 00 : 00 : 00 alanmi Exp $ ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "ioAbc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Io_WriteSmvCheckNames ( Abc_Ntk_t * pNtk ) ;
static int Io_WriteSmvOne ( FILE * pFile , Abc_Ntk_t * pNtk ) ;
static int Io_WriteSmvOneNode ( FILE * pFile , Abc_Obj_t * pNode ) ;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// This returns a pointer to a static area, so be careful in using results
// of this function i.e. don't call this twice in the same printf call.
//
// This function replaces '|' with '_' I think abc introduces '|' when
// flattening hierarchy. The '|' is interpreted as a or function by nusmv
// which is unfortunate. This probably should be fixed elsewhere.
static char * cleanUNSAFE ( const char * s )
{
char * t ;
static char buffer [ 1024 ] ;
assert ( strlen ( s ) < 1024 ) ;
strcpy ( buffer , s ) ;
for ( t = buffer ; * t ! = 0 ; + + t ) * t = ( * t = = ' | ' ) ? ' _ ' : * t ;
return buffer ;
}
static int hasPrefix ( const char * needle , const char * haystack )
{
return ( strncmp ( haystack , needle , strlen ( needle ) ) = = 0 ) ;
}
/**Function*************************************************************
Synopsis [ Writes the network in SMV format . ]
Description [ ]
SideEffects [ ]
SeeAlso [ ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int Io_WriteSmv ( Abc_Ntk_t * pNtk , char * pFileName )
{
Abc_Ntk_t * pExdc ;
FILE * pFile ;
assert ( Abc_NtkIsSopNetlist ( pNtk ) ) ;
if ( ! Io_WriteSmvCheckNames ( pNtk ) )
{
2015-02-08 07:29:14 +01:00
fprintf ( stdout , " Io_WriteSmv(): Signal names in this benchmark contain parentheses making them impossible to reproduce in the SMV format. Use \" short_names \" . \n " ) ;
2010-11-01 09:35:04 +01:00
return 0 ;
}
pFile = fopen ( pFileName , " w " ) ;
if ( pFile = = NULL )
{
fprintf ( stdout , " Io_WriteSmv(): Cannot open the output file. \n " ) ;
return 0 ;
}
fprintf ( pFile , " -- benchmark \" %s \" written by ABC on %s \n " , pNtk - > pName , Extra_TimeStamp ( ) ) ;
// write the network
Io_WriteSmvOne ( pFile , pNtk ) ;
// write EXDC network if it exists
pExdc = Abc_NtkExdc ( pNtk ) ;
if ( pExdc )
printf ( " Io_WriteSmv: EXDC is not written (warning). \n " ) ;
// finalize the file
fclose ( pFile ) ;
return 1 ;
}
/**Function*************************************************************
Synopsis [ Writes the network in SMV format . ]
Description [ ]
SideEffects [ ]
SeeAlso [ ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int Io_WriteSmvOne ( FILE * pFile , Abc_Ntk_t * pNtk )
{
ProgressBar * pProgress ;
Abc_Obj_t * pNode ;
int i ;
// write the PIs/POs/latches
fprintf ( pFile , " MODULE main \n " ) ; // nusmv needs top module to be main
fprintf ( pFile , " \n " ) ;
fprintf ( pFile , " VAR -- inputs \n " ) ;
Abc_NtkForEachPi ( pNtk , pNode , i )
fprintf ( pFile , " %s : boolean; \n " ,
cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( pNode ) ) ) ) ;
fprintf ( pFile , " \n " ) ;
fprintf ( pFile , " VAR -- state variables \n " ) ;
Abc_NtkForEachLatch ( pNtk , pNode , i )
fprintf ( pFile , " %s : boolean; \n " ,
cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( Abc_ObjFanout0 ( pNode ) ) ) ) ) ;
fprintf ( pFile , " \n " ) ;
// No outputs needed for NuSMV:
// TODO: Add sepcs by recognizing assume_.* and assert_.*
//
// Abc_NtkForEachPo( pNtk, pNode, i )
// fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) );
// write internal nodes
fprintf ( pFile , " DEFINE \n " ) ;
pProgress = Extra_ProgressBarStart ( stdout , Abc_NtkObjNumMax ( pNtk ) ) ;
Abc_NtkForEachNode ( pNtk , pNode , i )
{
Extra_ProgressBarUpdate ( pProgress , i , NULL ) ;
Io_WriteSmvOneNode ( pFile , pNode ) ;
}
Extra_ProgressBarStop ( pProgress ) ;
fprintf ( pFile , " \n " ) ;
fprintf ( pFile , " ASSIGN \n " ) ;
Abc_NtkForEachLatch ( pNtk , pNode , i )
{
int Reset = ( int ) ( ABC_PTRUINT_T ) Abc_ObjData ( pNode ) ;
assert ( Reset > = 1 ) ;
assert ( Reset < = 3 ) ;
if ( Reset ! = 3 )
{
fprintf ( pFile , " init(%s) := %d; \n " ,
cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( Abc_ObjFanout0 ( pNode ) ) ) ) ,
Reset - 1 ) ;
}
fprintf ( pFile , " next(%s) := " ,
cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( Abc_ObjFanout0 ( pNode ) ) ) ) ) ;
fprintf ( pFile , " %s; \n " ,
cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin0 ( Abc_ObjFanin0 ( pNode ) ) ) ) ) ;
}
fprintf ( pFile , " \n " ) ;
Abc_NtkForEachPo ( pNtk , pNode , i )
{
const char * n = cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin0 ( pNode ) ) ) ;
// fprintf( pFile, "-- output %s;\n", n );
if ( hasPrefix ( " assume_fair_ " , n ) )
{
fprintf ( pFile , " FAIRNESS %s; \n " , n ) ;
}
else if ( hasPrefix ( " Assert_ " , n ) | |
hasPrefix ( " assert_safety_ " , n ) )
{
fprintf ( pFile , " INVARSPEC %s; \n " , n ) ;
}
else if ( hasPrefix ( " assert_fair_ " , n ) )
{
fprintf ( pFile , " LTLSPEC G F %s; \n " , n ) ;
}
}
return 1 ;
}
/**Function*************************************************************
Synopsis [ Writes the network in SMV format . ]
Description [ ]
SideEffects [ ]
SeeAlso [ ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int Io_WriteSmvOneNode ( FILE * pFile , Abc_Obj_t * pNode )
{
int nFanins ;
assert ( Abc_ObjIsNode ( pNode ) ) ;
nFanins = Abc_ObjFaninNum ( pNode ) ;
if ( nFanins = = 0 )
{ // write the constant 1 node
assert ( Abc_NodeIsConst1 ( pNode ) ) ;
fprintf ( pFile , " %s " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( pNode ) ) ) ) ;
fprintf ( pFile , " := 1; \n " ) ;
}
else if ( nFanins = = 1 )
{ // write the interver/buffer
if ( Abc_NodeIsBuf ( pNode ) )
{
fprintf ( pFile , " %s := " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( pNode ) ) ) ) ;
fprintf ( pFile , " %s; \n " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin0 ( pNode ) ) ) ) ;
}
else
{
fprintf ( pFile , " %s := ! " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( pNode ) ) ) ) ;
fprintf ( pFile , " %s; \n " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin0 ( pNode ) ) ) ) ;
}
}
else
{ // write the AND gate
fprintf ( pFile , " %s " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanout0 ( pNode ) ) ) ) ;
fprintf ( pFile , " := %s & " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin0 ( pNode ) ) ) ) ;
fprintf ( pFile , " %s; \n " , cleanUNSAFE ( Abc_ObjName ( Abc_ObjFanin1 ( pNode ) ) ) ) ;
}
return 1 ;
}
/**Function*************************************************************
Synopsis [ Returns 1 if the names cannot be written into the bench file . ]
Description [ ]
SideEffects [ ]
SeeAlso [ ]
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int Io_WriteSmvCheckNames ( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj ;
char * pName ;
int i ;
Abc_NtkForEachObj ( pNtk , pObj , i )
for ( pName = Nm_ManFindNameById ( pNtk - > pManName , i ) ; pName & & * pName ; pName + + )
if ( * pName = = ' ( ' | | * pName = = ' ) ' )
return 0 ;
return 1 ;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END