Source

LIME / lib / gxfdump.awk

#!/usr/bin/awk -f
##################################################################
# This AWK script implements generation of .dot files from .gxf
#
#Copyright (C) 2008 NXP Semiconductors B.V.
#
#This file is part of LIME.
#
#LIME is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License version 2
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#LIME 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 LIME.  If not, see <http://www.gnu.org/licenses/>.
##################################################################
BEGIN { if (!OP) OP="dump" }

func handle(tag,body) { return handle_bindings(tag,handle_gxf(tag,body)) }

func fifoidx(f,c,p, r) { r=fifo_idx[f,c,p]
	if (r>0) return r-1
	r=port_idx[f,c,p]
	if (r>0) return r-1
	return ""
}

END { if (OP=="dump") for (f in files)  {
	    print f,nnodes[f]
	    for (i=1; i<=nnodes[f]; i++) {
	    	n=nodes[f,i]
		print n,nports[f,n]
		print "inputs:"
	        for (j=1; j<=ninports[f,n]; j++) {
		   p=inports[f,n,j]
		   print f,n,p,port_type[f,n,p],port_size[f,n,p],"'" port_modi[f,n,p] "'"
		}
		print "outputs:"
	        for (j=1; j<=noutports[f,n]; j++) {
		   p=outports[f,n,j]
		   print f,n,p,port_type[f,n,p],port_size[f,n,p],"'" port_modi[f,n,p] "'"
		}
	    }
	    for (i=1; i<=norder[f]; i++)
	    	print f,i,order[f,i]
      }
}

END { if (OP=="dot") for (f in files)  {
	    if (!edge_detail) printf "strict "
      	    print "digraph",dnode(alt(stem,f)),"{ splines=polyline; URL=\"" f "\""
	    for (i=1; i<=nnodes[f]; i++)
	    {
	    	n=nodes[f,i]
		if (!is_anyinstance(f,n)) continue

#"fontsize=26; "\
		printf "subgraph cluster_%s { "\
		       "rankdir=LR; "\
		       "splines=line; "\
		       "labelloc=%s; "\
		       "label=\"%s\"; "\
		       "style=filled; "\
		       "URL=\"doc-gen/%s.html\"\n", 
		       dnode(n),
		       (noutports[f,n]==0 ? "b" : "t"),
		       dnode(n),
		       node_stereotype[f,n]


	    if (node_detail) {
	    	c=base(f,n)
		# Internal nodes
		for (j=1; j<=nnodes[c]; j++)
			prnode(c,nodes[c,j],1,n "_")
		for (x in node_code) {
		    if (split(x,a,SUBSEP)!=3) fail("bad node_code")
		    if (a[1]!=f || a[2]!=c || !a[3]) continue
		    printf "code%s_%s [fontsize=8 label=\"%s\"]\n",
				dnode(n),a[3],gensub(/"/,"\\\\\"","g",gensub(/\n/,"\\\\l","g",node_code[x]))
		    for (j=1; j<=nports[f,n]; j++) {
		    	p=ports[f,n,j]
			if (node_code[x] ~ "\\<" p "\\>")
				print dnode(n) "_" p,"->", "code" dnode(n) "_" a[3],"[arrowhead=none","style=\"dashed\"]"
		    }
		}
		# Inner edges
	    	for (j=1; j<=nedges[c]; j++) {
	    	    split(edge_from[c,j],fr,SUBSEP)
	    	    split(edge_to[c,j],to,SUBSEP)
		    predge(n "_" fr[1],fr[2],n "_" to[1],to[2],c,j,"")
	    	}
		# bindings
		for (j=1; j<=nint_edge[c]; j++) {
			if (split(int_edge[c,j],ep,SUBSEP)!=2) continue
			if (!ep[1] || !ep[2]) continue
			print n "_" ep[1],"->", n "_" ep[2],"[arrowhead=none","style=\"dashed\"]"
		}
	    }

		# Outer ports
		printf "{%s\n", (do_source_rank ? " rank=source" : "")
	        for (j=1; j<=ninports[f,n]; j++) {
		   p=inports[f,n,j]
		   printf "%s_%s [fontsize=8 style=filled color=white shape=\"%s\" label=\"%s\" %s]\n",
			dnode(n),p,
		        "trapezium",
			(1 ? p : port_type[f,n,p] " " p	dotconv(get_portsizes(f,n,p))),
			urlWrap(node_stereotype[f,n] ":" p)
		}
		print "}"
		print "{ rank=sink"
	        for (j=1; j<=noutports[f,n]; j++) {
		   p=outports[f,n,j]
		   printf "%s_%s [fontsize=8 style=filled color=white shape=\"%s\" label=\"%s\" %s]\n",
			dnode(n),p,
		        "invtrapezium",
			(1 ? p : port_type[f,n,p] " " p	dotconv(get_portsizes(f,n,p))),
		       urlWrap(node_stereotype[f,n] ":" p)
		}
		print "}"

		# find local state self-references in this node
	if (!node_detail) {
		s=base(f,n)
		for (j=1; j<=nnodes[s]; j++) {
			sn=nodes[s,j]
			for (k=1; k<=nstateports[s,sn,"read"]; k++) {
			    p=stateports[s,sn,"read",k]
			    #print s,n,sn,p,peer_node[s,sn,p] >STDERR
			    if (peer_node[s,sn,p]!=sn) continue
			    if(peer_dir[s,sn,p]=="read")
				predge(n,peer_port[s,sn,p],n,p,n,peer_edge[s,sn,p],"_")
			    else 
				predge(n,p,n,peer_port[s,sn,p],n,peer_edge[s,sn,p],"_")
			}
		}
	}
		print "}"
	    }
	    for (i=1; i<=nedges[f]; i++) 
	    {
	    	split(edge_from[f,i],fr,SUBSEP)
	    	split(edge_to[f,i],to,SUBSEP)
		if (!is_anyinstance(f,fr[1]) || !is_anyinstance(f,to[1]))
			continue
		prEdge(fr[1],fr[2],to[1],to[2],f,i,"_")
	    }
	    print "}"
      }
}

func prnode(f,n,not,pr, done,j,p)
{
	printf "%s%s [URL=\"doc-gen/%s.html#NWI-%s\" shape=Mrecord label=\"{",pr,dnode(n),f,n
	done=0
        for (j=1; j<=ninports[f,n]; j++) {
	   p=inports[f,n,j]
	   printf "%s <%s> %s",
		(done ? "|" : "{"),
		p,
		(not ? p : port_type[f,n,p] " " p dotconv(get_portsizes(f,n,p)))
	   done=1
	}
	printf "%s %s()",(done ? " } |" : ""),dnode(n)
	done=0
        for (j=1; j<=noutports[f,n]; j++) {
	   p=outports[f,n,j]
	   printf "%s <%s> %s",
		(done ? "|" : "| {"),
		p,
		(not ? p : port_type[f,n,p] " " p dotconv(get_portsizes(f,n,p)))
	   done=1
	}
	printf "%s",(done ? "}" : "")

	print "}\"]"
}
func dotconv(s) {
	return gensub(/[<>]/,"\\\\&","g",s)
}
func nodeconv(s) {
	gsub(/[:]/,"_",s)
	gsub(/[+]/,"plus",s)
	gsub(/[-]/,"min",s)
	gsub(/[*]/,"times",s)
	return dotconv(s)
}
func prEdge(fn,fp,tn,tp,f,i,sep,style) {
	if (edge_detail) return predge_detail(fn,fp,tn,tp,f,i,sep,style)
	return predge(fn,fp,tn,tp,f,i,sep,style)
}

func predge_detail(fn,fp,tn,tp,f,i,sep,style) {
	if (!sep) sep=":"
	printf "%s_%i [label=\"{ {<in> %s%s} | %s | {<out> %s%s} }\" shape=record %s %s]\n",
		nodeconv(edge_type[f,i]),
		++number[edge_type[f,i]],
		port_type[f,fn,fp],dotconv(get_portsizes(f,fn,fp)),
		edge_type[f,i],
		port_type[f,tn,tp], dotconv(get_portsizes(f,tn,tp)),
		attWrap("style",style),
	        urlWrap(edge_id[f,i])
    	printf "%s%s%s -> %s_%i:in%s [%s]\n",
		dnode(fn),sep,fp,
		nodeconv(edge_type[f,i]), number[edge_type[f,i]],
		(1 ? "" : ":n"),
		tn!=fn ? "taillabel=\"" fifoidx(f,fn,fp) "\"" : ""
    	printf "%s_%i:out%s -> %s%s%s [%s]\n",
		nodeconv(edge_type[f,i]), number[edge_type[f,i]],
		(1 ? "" : ":s"),
		dnode(tn),sep,tp,
		tn!=fn ? "headlabel=\"" fifoidx(f,tn,tp) "\"" : ""
}
func predge(fn,fp,tn,tp,f,i,sep,style) {
	if (!sep) sep=":"
    	printf "%s%s%s -> %s%s%s [%s %s labelangle=180 headlabel=\"%s\" taillabel=\"%s\"]\n",
		dnode(fn),sep,fp,
		dnode(tn),sep,tp,
		attWrap("label",edge_type[f,i]),
		attWrap("style",style),
		dotconv(get_portsizes(f,tn,tp)),
		dotconv(get_portsizes(f,fn,fp)) #, wrap(edge_id[f,i],"URL=\"#","\"")
}

func predge_old(fn,fp,tn,tp,f,i,sep) {
	if (!sep) sep=":"
    	printf "%s%s%s -> %s%s%s [%s %s %s]\n",
		dnode(fn),sep,fp,
		dnode(tn),sep,tp,
		edgetype(f,i),
		tn==fn ? "" : "headlabel=\"" fifoidx(f,tn,tp) "\"",
		tn==fn ? "" : "taillabel=\"" fifoidx(f,fn,fp) "\""
}
func edgetype(f,i) {
	return edge_type[f,i] ? "label=\"" edge_type[f,i] "\"" : ""
}

func dnode(n) { return gensub(/[.@\$-]/,"_","g",n) }

END { if (OP=="dot2") for (f in files)  {
      	    print "digraph",dnode(alt(stem,f)),"{"
	    for (i=1; i<=nnodes[f]; i++) {
	    	n=nodes[f,i]
		if (!is_anyinstance(f,n)) continue
		prnode(f,n)

		# find local state self-references in this node
		for (j=1; j<=nnodes[n]; j++) {
			sn=nodes[n,j]
			for (k=1; k<=nstateports[n,sn,"read"]; k++) {
			    p=stateports[n,sn,"read",k]
			    if (peer_node[n,sn,p]==sn)
			    {
			      if(peer_dir[n,sn,p]=="read")
				predge_old(n,peer_port[n,sn,p],n,p,n,peer_edge[n,sn,p])
			      else 
				predge_old(n,p,n,peer_port[n,sn,p],n,peer_edge[n,sn,p])
			    }
			}
		}
	    }
	    for (i=1; i<=nedges[f]; i++) {
	    	split(edge_from[f,i],fr,SUBSEP)
	    	split(edge_to[f,i],to,SUBSEP)
		predge_old(fr[1],fr[2],to[1],to[2],f,i)
	    }
	    print "}"
      }
}

@include gxf-parser.awk