Create Graphviz dot library/import

190 views Asked by At

TLDR

To enable me to have text based graphical documentation that is as auto-generated as possible, I would like to be able to define several node types, and have those definitions be importable

Longer explanation

I am working on a project where I auto generate a Graphviz dot RTL diagram for a hardware design written in VHDL. The definition for the nodes I am defining is complicated and gross and should be hidden from the user. I would like to be able to define several node types, and have those definitions be importable and easily instantiated. I am starting to get the feeling graphviz/dot may not be the correct solution, and I'll happily abandon Graphviz for something better. I just want to generate text based graphical documentation that is as auto-generated as possible. Currently I generate a complicated node definition like:

    Full_Adder_1bit [shape=plaintext, label=<
      <table border='1' cellborder='0' cellspacing='0'>
        <tr><td>Full_Adder_1bit</td></tr>
        <tr>
          <td><table border='0' cellborder='1' cellspacing='0' color='green'>
            <tr><td port='A'> A </td></tr>
            <tr><td port='B'> B </td></tr>
            <tr><td port='Cin'> Cin </td></tr>
          </table></td>
          <td><table border='0' cellborder='1' cellspacing='0' color='red'>
            <tr><td port='Sum'> Sum </td></tr>
            <tr><td port='Cout'> Cout </td></tr>
          </table></td>
        </tr>
      </table> >]

And in order for a user to make use of this to document their design they would have to use the node keyword properly and then create the nodes/ports to connect.

    node [shape=plaintext, label=<
      <table border='1' cellborder='0' cellspacing='0'>
        <tr><td>Full_Adder_1bit</td></tr>
        <tr>
          <td><table border='0' cellborder='1' cellspacing='0' color='green'>
            <tr><td port='A'> A </td></tr>
            <tr><td port='B'> B </td></tr>
            <tr><td port='Cin'> Cin </td></tr>
          </table></td>
          <td><table border='0' cellborder='1' cellspacing='0' color='red'>
            <tr><td port='Sum'> Sum </td></tr>
            <tr><td port='Cout'> Cout </td></tr>
          </table></td>
        </tr>
      </table> >]

    // -- MAIN --
    add1:Cout -> add2:Cin
    add2:Cout -> add3:Cin
    add3:Cout -> add4:Cin

This question does not answer my question because what I would like to do is this:

lib.dot

    Full_Adder_1bit [shape=plaintext, label=<
      <table border='1' cellborder='0' cellspacing='0'>
        <tr><td>Full_Adder_1bit</td></tr>
        <tr>
          <td><table border='0' cellborder='1' cellspacing='0' color='green'>
            <tr><td port='A'> A </td></tr>
            <tr><td port='B'> B </td></tr>
            <tr><td port='Cin'> Cin </td></tr>
          </table></td>
          <td><table border='0' cellborder='1' cellspacing='0' color='red'>
            <tr><td port='Sum'> Sum </td></tr>
            <tr><td port='Cout'> Cout </td></tr>
          </table></td>
        </tr>
      </table> >]

rtl.dot

    include(`lib.dot')

    add1 : instance of (Full_Adder_1bit)  
    add2 : instance of (Full_Adder_1bit)    
    add3 : instance of (Full_Adder_1bit)  
    add4 : instance of (Full_Adder_1bit)  
        
    // -- MAIN --
    add1:Cout -> add2:Cin   
    add2:Cout -> add3:Cin    
    add3:Cout -> add4:Cin  
1

There are 1 answers

1
Jens On

You could use a c-preprocessor

or use subgraph's to control which nodes get which label label (added some gates to get a more illustrative example)

e.g.

digraph G {
    rankdir=LR
    
// definitions
    subgraph Full_Adder_1bit { node [shape=plaintext, label=<
      <table border='1' cellborder='0' cellspacing='0'>
        <tr><td>Full_Adder_1bit</td></tr>
        <tr>
          <td><table border='0' cellborder='1' cellspacing='0' color='green'>
            <tr><td port='A'> A </td></tr>
            <tr><td port='B'> B </td></tr>
            <tr><td port='Cin'> Cin </td></tr>
          </table></td>
          <td><table border='0' cellborder='1' cellspacing='0' color='red'>
            <tr><td port='Sum'> Sum </td></tr>
            <tr><td port='Cout'> Cout </td></tr>
          </table></td>
        </tr>
      </table> >]
    }
    subgraph NAND {
        node[label=<<table border="0" cellspacing="0" cellborder="1">
            <tr><td port='A'>A</td><td port='out' rowspan="2">NAND</td></tr>
            <tr><td port='B'>B</td></tr>
            </table>> shape=none margin=0]
    }
    subgraph AND {
        node[label=<<table border="0" cellspacing="0" cellborder="1">
            <tr><td port='A'>A</td><td port='out' rowspan="2">AND</td></tr>
            <tr><td port='B'>B</td></tr>
            </table>> shape=none margin=0]
    }
    subgraph NOR {
        node[label=<<table border="0" cellspacing="0" cellborder="1">
            <tr><td port='A'>A</td><td port='out' rowspan="2">NOR</td></tr>
            <tr><td port='B'>B</td></tr>
            </table>> shape=none margin=0]
    }
    subgraph OR {
        node[label=<<table border="0" cellspacing="0" cellborder="1">
            <tr><td port='A'>A</td><td port='out' rowspan="2">OR</td></tr>
            <tr><td port='B'>B</td></tr>
            </table>> shape=none margin=0]
    }
    subgraph NOT {
        node[label=<<table border="0" cellspacing="0" cellborder="1">
            <tr><td port='A'>A</td><td port='out' >NOT</td></tr>
            </table>> shape=none margin=0]
    }
    subgraph Point { node[shape=point xlabel="\N"] }



// declarations
    subgraph Point { A_xor B_xor out_xor }
    subgraph AND { and1 and2 }
    subgraph NOT { not1 not2 }
    subgraph OR { or1 }
// connections
    A_xor->and1:A
    A_xor->not1:A not1:out->and2:A
    B_xor->and2:B
    B_xor->not2:A not2:out->and1:B
    and1:out->or1:A
    and2:out->or1:B
    or1:out->out_xor


    subgraph Full_Adder_1bit {
        add1:Cout -> add2:Cin
        add2:Cout -> add3:Cin
        add3:Cout -> add4:Cin
    }

}

enter image description here