#!/usr/bin/python
#    This is a component of emc2
#    Copyright 2007 Jeff Epler <jepler@unpythonic.net>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os
import sys
import commands

def to_dot_name(s):
    s = s.replace(".", "_")
    s = s.replace("-", "_")
    return s

def port(s):
    return s.rsplit(".", 1)[0]

def leaf(s):
    return s.rsplit(".", 1)[1]

def to_leaf_name(s):
    return to_dot_name(s.rsplit(".", 1)[1])

def to_port_name(s):
    return to_dot_name(s.rsplit(".", 1)[0])

def to_node_name(s):
    if "." in s:
        return "%s:%s" % (to_port_name(s), to_leaf_name(s))
    else:
        n = to_dot_name(s)
        return "%s:%s" % (n, n)

def direction(s):
    o = commands.getoutput("halcmd -s show pin %s" % s)
    if "IO" in o: return "both"
    if "OUT" in o: return 0
    return 1

print "digraph net {"
print "    node [shape=record];"
nodes = {}
edges = set()
if len(sys.argv) == 2:
    source = open(sys.argv[1])
else:
    source = os.popen("halcmd save netl") 
for line in source:
    words = line.split()
    if not words or words[0] != "net": continue
    signal = words[1]

    ns = "sig_" + to_dot_name(signal)
    print "    %s [shape=diamond, label=\"%s\"]" % (ns, signal)

    for i, w in enumerate(words[2:]):
        if w.startswith("<") or w.startswith("="): continue
        nw = to_node_name(w)
        pn = port(w)
        if pn in nodes:
            nodes[pn].append(w)
        else:
            nodes[pn] = [w]
        d = direction(w)
        if d == "both":
            edges.add((ns, nw, "both",2))
        elif d:
            edges.add((ns, nw, "forward",1))
        else:
            edges.add((nw, ns, "forward",3))

print
for n, v in nodes.items():
    label = "|".join("<%s>%s" % (to_leaf_name(i), leaf(i)) for i in v if i != n)
    dn = to_dot_name(n)
    if label:
        print "    %s [label=\"<%s>%s|%s\"];" % (dn, dn, n, label)
    else:
        print "    %s [label=\"<%s>%s\"];" % (dn, dn, n)

print
for a,b,c,d in edges:
    print "    %s -> %s" % (a, b),
    if c or d:
        print "[",
        if c: print "dir=%s" % c,
        if c and d: print ",",
        if d: print "weight=%s" % d,
        print "]",
    print ";"
print "} }"

