ivyShow.c 12.5 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/**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 $]

***********************************************************************/

Alan Mishchenko committed
21
#include "ivy.h"
Alan Mishchenko committed
22

23 24 25
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
26 27 28 29
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

Alan Mishchenko committed
30 31
static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold );

Alan Mishchenko committed
32 33 34 35 36 37
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

Alan Mishchenko committed
38 39 40 41 42 43 44 45 46 47 48 49
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold )
{
    extern void Abc_ShowFile( char * FileNameDot );
Alan Mishchenko committed
50
    static int Counter = 0;
Alan Mishchenko committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    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*************************************************************

Alan Mishchenko committed
71 72 73 74 75 76 77 78 79 80
  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     []

***********************************************************************/
Alan Mishchenko committed
81
void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold )
Alan Mishchenko committed
82 83
{
    FILE * pFile;
Alan Mishchenko committed
84
    Ivy_Obj_t * pNode, * pTemp, * pPrev;
Alan Mishchenko committed
85 86
    int LevelMax, Level, i;

Alan Mishchenko committed
87
    if ( Ivy_ManNodeNum(pMan) > 200 )
Alan Mishchenko committed
88 89 90 91 92 93 94 95 96 97 98 99
    {
        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 )
100
        Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i )
Alan Mishchenko committed
101 102 103
            pNode->fMarkB = 1;

    // compute levels
Alan Mishchenko committed
104
    LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig );
Alan Mishchenko committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

    // 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" );
Alan Mishchenko committed
166
    fprintf( pFile, "Time was %s. ",  Extra_TimeStamp() );
Alan Mishchenko committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180
    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=\"" );
Alan Mishchenko committed
181
    fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax );
Alan Mishchenko committed
182 183 184 185 186 187 188 189 190 191 192 193 194
    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
Alan Mishchenko committed
195
    Ivy_ManForEachCo( pMan, pNode, i )
Alan Mishchenko committed
196 197 198
    {
        if ( fHaig || pNode->pEquiv == NULL )
            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
Alan Mishchenko committed
199
                (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
Alan Mishchenko committed
200 201
        else
            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
Alan Mishchenko committed
202 203 204
                (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") );
Alan Mishchenko committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218
        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 );
Alan Mishchenko committed
219
        Ivy_ManForEachObj( pMan, pNode, i )
Alan Mishchenko committed
220 221 222 223 224 225 226
        {
            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, 
Alan Mishchenko committed
227
                    Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" );
Alan Mishchenko committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
            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
Alan Mishchenko committed
244
    if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 )
Alan Mishchenko committed
245
    {
Alan Mishchenko committed
246
        pNode = Ivy_ManConst1(pMan);
Alan Mishchenko committed
247 248 249 250 251 252 253
        // 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
Alan Mishchenko committed
254
    Ivy_ManForEachCi( pMan, pNode, i )
Alan Mishchenko committed
255 256 257
    {
        if ( fHaig || pNode->pEquiv == NULL )
            fprintf( pFile, "  Node%d%s [label = \"%d%s\"", pNode->Id, 
Alan Mishchenko committed
258
                (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") );
Alan Mishchenko committed
259 260
        else
            fprintf( pFile, "  Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, 
Alan Mishchenko committed
261 262 263
                (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") );
Alan Mishchenko committed
264 265 266 267 268 269 270 271 272
        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" );
Alan Mishchenko committed
273 274
    Ivy_ManForEachCo( pMan, pNode, i )
        fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
Alan Mishchenko committed
275 276

    // generate edges
Alan Mishchenko committed
277
    Ivy_ManForEachObj( pMan, pNode, i )
Alan Mishchenko committed
278
    {
Alan Mishchenko committed
279
        if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) )
Alan Mishchenko committed
280 281
            continue;
        // generate the edge from this node to the next
Alan Mishchenko committed
282
        fprintf( pFile, "Node%d%s",  pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") );
Alan Mishchenko committed
283
        fprintf( pFile, " -> " );
Alan Mishchenko committed
284
        fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") );
Alan Mishchenko committed
285
        fprintf( pFile, " [" );
Alan Mishchenko committed
286 287
        fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" );
//        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 )
Alan Mishchenko committed
288 289 290
//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
        fprintf( pFile, "]" );
        fprintf( pFile, ";\n" );
Alan Mishchenko committed
291
        if ( !Ivy_ObjIsNode(pNode) )
Alan Mishchenko committed
292 293 294 295
            continue;
        // generate the edge from this node to the next
        fprintf( pFile, "Node%d",  pNode->Id );
        fprintf( pFile, " -> " );
Alan Mishchenko committed
296
        fprintf( pFile, "Node%d%s",  Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") );
Alan Mishchenko committed
297
        fprintf( pFile, " [" );
Alan Mishchenko committed
298 299
        fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" );
//        if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 )
Alan Mishchenko committed
300 301 302 303
//        fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
        fprintf( pFile, "]" );
        fprintf( pFile, ";\n" );
        // generate the edges between the equivalent nodes
Alan Mishchenko committed
304
        if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 )
Alan Mishchenko committed
305 306
        {
            pPrev = pNode;
Alan Mishchenko committed
307
            for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) )
Alan Mishchenko committed
308 309 310 311
            {
                fprintf( pFile, "Node%d",  pPrev->Id );
                fprintf( pFile, " -> " );
                fprintf( pFile, "Node%d",  pTemp->Id );
Alan Mishchenko committed
312
                fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" );
Alan Mishchenko committed
313 314 315 316 317 318 319
                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 );
Alan Mishchenko committed
320
            fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" );
Alan Mishchenko committed
321 322 323 324 325 326 327 328 329 330 331
            fprintf( pFile, ";\n" );
        }
    }

    fprintf( pFile, "}" );
    fprintf( pFile, "\n" );
    fprintf( pFile, "\n" );
    fclose( pFile );

    // unmark nodes
    if ( vBold )
332
        Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i )
Alan Mishchenko committed
333 334 335 336 337 338 339 340 341
            pNode->fMarkB = 0;
}


////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


342 343
ABC_NAMESPACE_IMPL_END