summaryrefslogtreecommitdiffstats
path: root/src/base/io/ioWriteSmv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/io/ioWriteSmv.c')
-rw-r--r--src/base/io/ioWriteSmv.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/src/base/io/ioWriteSmv.c b/src/base/io/ioWriteSmv.c
new file mode 100644
index 00000000..c767bcaa
--- /dev/null
+++ b/src/base/io/ioWriteSmv.c
@@ -0,0 +1,265 @@
+/**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) )
+ {
+ fprintf( stdout, "Io_WriteSmv(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the SMV format. Use \"short_names\".\n" );
+ 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
+