text: /**CFile****************************************************************
  
    FileName    [ivyShow.c]
  
    SystemName  [ABC: Logic synthesis and verification system.]
  
    PackageName [And-Inverter Graph package.]
  
    Synopsis    [Visualization of HAIG.]
  
    Author      [Alan Mishchenko]
    
    Affiliation [UC Berkeley]
  
    Date        [Ver. 1.0. Started - May 11, 2006.]
  
    Revision    [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
  
  ***********************************************************************/
  
  #include "ivy.h"
  
  ////////////////////////////////////////////////////////////////////////
  ///                        DECLARATIONS                              ///
  ////////////////////////////////////////////////////////////////////////
  
  static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold );
  
  ////////////////////////////////////////////////////////////////////////
  ///                     FUNCTION DEFINITIONS                         ///
  ////////////////////////////////////////////////////////////////////////
  
  /**Function*************************************************************
  
    Synopsis    []
  
    Description []
                 
    SideEffects []
  
    SeeAlso     []
  
  ***********************************************************************/
  void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
  {
      extern void Abc_ShowFile( char * FileNameDot );
      static Counter = 0;
      char FileNameDot[200];
      FILE * pFile;
      // create the file name
  //    Ivy_ShowGetFileName( pMan->pName, FileNameDot );
      sprintf( FileNameDot, "temp%02d.dot", Counter++ );
      // check that the file can be opened
      if ( (pFile = fopen( FileNameDot, "w" )) == NULL )
      {
          fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot );
          return;
      }
      fclose( pFile );
      // generate the file
      Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold );
      // visualize the file 
      Abc_ShowFile( FileNameDot );
  }
  
  /**Function*************************************************************
  
    Synopsis    [Writes the graph structure of AIG for DOT.]
  
    Description [Useful for graph visualization using tools such as GraphViz: 
    http://www.graphviz.org/]
    
    SideEffects []
  
    SeeAlso     []
  
  ***********************************************************************/
  void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
  {
      FILE * pFile;
      Ivy_Obj_t * pNode, * pTemp, * pPrev;
      int LevelMax, Level, i;
  
      if ( Ivy_ManNodeNum(pMan) > 200 )
      {
          fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" );
          return;
      }
      if ( (pFile = fopen( pFileName, "w" )) == NULL )
      {
          fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName );
          return;
      }
  
      // mark the nodes
      if ( vBold )
          Vec_PtrForEachEntry( vBold, pNode, i )
              pNode->fMarkB = 1;
  
      // compute levels
      LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig );
  
      // write the DOT header
      fprintf( pFile, "# %s\n",  "AIG structure generated by IVY package" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "digraph AIG {\n" );
      fprintf( pFile, "size = \"7.5,10\";\n" );
  //  fprintf( pFile, "ranksep = 0.5;\n" );
  //  fprintf( pFile, "nodesep = 0.5;\n" );
      fprintf( pFile, "center = true;\n" );
  //  fprintf( pFile, "orientation = landscape;\n" );
  //  fprintf( pFile, "edge [fontsize = 10];\n" );
  //  fprintf( pFile, "edge [dir = none];\n" );
      fprintf( pFile, "edge [dir = back];\n" );
      fprintf( pFile, "\n" );
  
      // labels on the left of the picture
      fprintf( pFile, "{\n" );
      fprintf( pFile, "  node [shape = plaintext];\n" );
      fprintf( pFile, "  edge [style = invis];\n" );
      fprintf( pFile, "  LevelTitle1 [label=\"\"];\n" );
      fprintf( pFile, "  LevelTitle2 [label=\"\"];\n" );
      // generate node names with labels
      for ( Level = LevelMax; Level >= 0; Level-- )
      {
          // the visible node name
          fprintf( pFile, "  Level%d", Level );
          fprintf( pFile, " [label = " );
          // label name
          fprintf( pFile, "\"" );
          fprintf( pFile, "\"" );
          fprintf( pFile, "];\n" );
      }
  
      // genetate the sequence of visible/invisible nodes to mark levels
      fprintf( pFile, "  LevelTitle1 ->  LevelTitle2 ->" );
      for ( Level = LevelMax; Level >= 0; Level-- )
      {
          // the visible node name
          fprintf( pFile, "  Level%d",  Level );
          // the connector
          if ( Level != 0 )
              fprintf( pFile, " ->" );
          else
              fprintf( pFile, ";" );
      }
      fprintf( pFile, "\n" );
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
  
      // generate title box on top
      fprintf( pFile, "{\n" );
      fprintf( pFile, "  rank = same;\n" );
      fprintf( pFile, "  LevelTitle1;\n" );
      fprintf( pFile, "  title1 [shape=plaintext,\n" );
      fprintf( pFile, "          fontsize=20,\n" );
      fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
      fprintf( pFile, "          label=\"" );
      fprintf( pFile, "%s", "AIG structure visualized by ABC" );
      fprintf( pFile, "\\n" );
      fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" );
      fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
      fprintf( pFile, "\"\n" );
      fprintf( pFile, "         ];\n" );
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
  
      // generate statistics box
      fprintf( pFile, "{\n" );
      fprintf( pFile, "  rank = same;\n" );
      fprintf( pFile, "  LevelTitle2;\n" );
      fprintf( pFile, "  title2 [shape=plaintext,\n" );
      fprintf( pFile, "          fontsize=18,\n" );
      fprintf( pFile, "          fontname = \"Times-Roman\",\n" );
      fprintf( pFile, "          label=\"" );
      fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax );
      fprintf( pFile, "\\n" );
      fprintf( pFile, "\"\n" );
      fprintf( pFile, "         ];\n" );
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
  
      // generate the COs
      fprintf( pFile, "{\n" );
      fprintf( pFile, "  rank = same;\n" );
      // the labeling node of this level
      fprintf( pFile, "  Level%d;\n",  LevelMax );
      // generate the CO nodes
      Ivy_ManForEachCo( pMan, pNode, i )
      {
          if ( fHaig || pNode->pEquiv == NULL )
              fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
                  (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
          else
              fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
                  (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), 
                      Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
          fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") );
          fprintf( pFile, ", color = coral, fillcolor = coral" );
          fprintf( pFile, "];\n" );
      }
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
  
      // generate nodes of each rank
      for ( Level = LevelMax - 1; Level > 0; Level-- )
      {
          fprintf( pFile, "{\n" );
          fprintf( pFile, "  rank = same;\n" );
          // the labeling node of this level
          fprintf( pFile, "  Level%d;\n",  Level );
          Ivy_ManForEachObj( pMan, pNode, i )
          {
              if ( (int)pNode->Level != Level )
                  continue;
              if ( fHaig || pNode->pEquiv == NULL )
                  fprintf( pFile, "  Node%d [label = \"%d\"", pNode->Id, pNode->Id );
              else 
                  fprintf( pFile, "  Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, 
                      Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
              fprintf( pFile, ", shape = ellipse" );
              if ( vBold && pNode->fMarkB )
                  fprintf( pFile, ", style = filled" );
              fprintf( pFile, "];\n" );
          }
          fprintf( pFile, "}" );
          fprintf( pFile, "\n" );
          fprintf( pFile, "\n" );
      }
  
      // generate the CI nodes
      fprintf( pFile, "{\n" );
      fprintf( pFile, "  rank = same;\n" );
      // the labeling node of this level
      fprintf( pFile, "  Level%d;\n",  0 );
      // generate constant node
      if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 )
      {
          pNode = Ivy_ManConst1(pMan);
          // check if the costant node is present
          fprintf( pFile, "  Node%d [label = \"Const1\"", pNode->Id );
          fprintf( pFile, ", shape = ellipse" );
          fprintf( pFile, ", color = coral, fillcolor = coral" );
          fprintf( pFile, "];\n" );
      }
      // generate the CI nodes
      Ivy_ManForEachCi( pMan, pNode, i )
      {
          if ( fHaig || pNode->pEquiv == NULL )
              fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
                  (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") );
          else
              fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
                  (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), 
                      Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
          fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") );
          fprintf( pFile, ", color = coral, fillcolor = coral" );
          fprintf( pFile, "];\n" );
      }
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
  
      // generate invisible edges from the square down
      fprintf( pFile, "title1 -> title2 [style = invis];\n" );
      Ivy_ManForEachCo( pMan, pNode, i )
          fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
  
      // generate edges
      Ivy_ManForEachObj( pMan, pNode, i )
      {
          if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) )
              continue;
          // generate the edge from this node to the next
          fprintf( pFile, "Node%d%s",  pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
          fprintf( pFile, " -> " );
          fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") );
          fprintf( pFile, " [" );
          fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" );
  //        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
  //        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
          fprintf( pFile, "]" );
          fprintf( pFile, ";\n" );
          if ( !Ivy_ObjIsNode(pNode) )
              continue;
          // generate the edge from this node to the next
          fprintf( pFile, "Node%d",  pNode->Id );
          fprintf( pFile, " -> " );
          fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") );
          fprintf( pFile, " [" );
          fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" );
  //        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
  //        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
          fprintf( pFile, "]" );
          fprintf( pFile, ";\n" );
          // generate the edges between the equivalent nodes
          if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
          {
              pPrev = pNode;
              for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
              {
                  fprintf( pFile, "Node%d",  pPrev->Id );
                  fprintf( pFile, " -> " );
                  fprintf( pFile, "Node%d",  pTemp->Id );
                  fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
                  fprintf( pFile, ";\n" );
                  pPrev = pTemp;
              }
              // connect the last node with the first
              fprintf( pFile, "Node%d",  pPrev->Id );
              fprintf( pFile, " -> " );
              fprintf( pFile, "Node%d",  pNode->Id );
              fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
              fprintf( pFile, ";\n" );
          }
      }
  
      fprintf( pFile, "}" );
      fprintf( pFile, "\n" );
      fprintf( pFile, "\n" );
      fclose( pFile );
  
      // unmark nodes
      if ( vBold )
          Vec_PtrForEachEntry( vBold, pNode, i )
              pNode->fMarkB = 0;
  }
  
  
  ////////////////////////////////////////////////////////////////////////
  ///                       END OF FILE                                ///
  ////////////////////////////////////////////////////////////////////////
  
  
  