1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
34 #include "sigtyperules.hh"
37 #include "sigToGraph.hh"
38 #include "sigraterules.hh"
43 static void recdraw(Tree sig
, set
<Tree
>& drawn
, ofstream
& fout
, RateInferrer
* R
);
44 static string
commonattr(Type t
);
45 static string
nodeattr(Type t
);
46 static string
edgeattr(Type t
, int rate
);
47 static string
sigLabel(Tree sig
);
51 * Draw a list of signals as a directed graph using graphviz's dot language
53 void sigToGraph (Tree L
, ofstream
& fout
, RateInferrer
* R
)
55 set
<Tree
> alreadyDrawn
;
57 fout
<< "strict digraph loopgraph {\n"
58 << " rankdir=LR; node [fontsize=10];"
62 recdraw(hd(L
), alreadyDrawn
, fout
, R
);
64 fout
<< "OUTPUT_" << out
<< "[color=\"red2\" style=\"filled\" fillcolor=\"pink\"];" << endl
;
65 fout
<< 'S' << hd(L
) << " -> " << "OUTPUT_" << out
++ << "[" << edgeattr(getCertifiedSigType(hd(L
)), R
->rate(hd(L
))) << "];" << endl
;
73 /******************************* IMPLEMENTATION ***********************************/
77 * Draw recursively a signal
79 static void recdraw(Tree sig
, set
<Tree
>& drawn
, ofstream
& fout
, RateInferrer
* R
)
81 //cerr << ++TABBER << "ENTER REC DRAW OF " << sig << "$" << *sig << endl;
85 if (drawn
.count(sig
) == 0) {
86 // the signal has never been drawn
87 drawn
.insert(sig
); // remember it
89 // it's a list of signals : we draw each signal of the list
91 recdraw(hd(sig
), drawn
, fout
, R
);
93 } while (isList(sig
));
95 // it is a regular signal
96 // first draw the node
97 fout
<< 'S' << sig
<< "[label=\"" << sigLabel(sig
) << "\""
98 << nodeattr(getCertifiedSigType(sig
)) << "];"
101 // then draw the subsignals if any
102 n
= getSubSignals(sig
, subsig
);
105 // check special recursion case, recreate a vector of subsignals instead of the
106 // list provided by getSubSignal
107 if (n
==1 && isList(subsig
[0])) {
108 assert(isRec(sig
,id
,body
));
114 subsig
.push_back(hd(L
));
120 // draw each subsignal
121 for (int i
=0; i
<n
; i
++) {
122 recdraw(subsig
[i
], drawn
, fout
, R
);
123 if (isRec(subsig
[i
],id
,body
)) {
124 // special case when source is a recursive group, we don't want a rate
125 fout
<< 'S' << subsig
[i
] << " -> " << 'S' << sig
129 // special case when source is a recursive group, we don't want a rate
130 fout
<< 'S' << subsig
[i
] << " -> " << 'S' << sig
131 << "[" << edgeattr(getCertifiedSigType(subsig
[i
]), R
->rate(subsig
[i
])) << "];"
138 //cerr << --TABBER << "EXIT REC DRAW OF " << sig << endl;
143 * Convert a signal type into attributes common to edges and nodes
145 static string
commonattr(Type t
)
150 if (t
->nature()==kInt
) {
151 s
+= " color=\"blue\"";
153 s
+= " color=\"red\"";
157 if (t
->vectorability()==kVect
&& t
->variability()==kSamp
) {
158 s
+= " style=\"bold\"";
164 * Convert a signal type into edge attributes
166 static string
edgeattr(Type t
, int rate
)
170 Type b
= t
->dimensions(d
);
174 // add rate information as label at the head of the arrow
176 for (int i
=0; i
<d
.size(); i
++) {
177 s
+= subst("[$0]", T(d
[i
]));
179 s
+= subst("x$0\" fontsize=8", T(rate
));
186 * Convert a signal type into node attributes
188 static string
nodeattr(Type t
)
190 string s
= commonattr(t
);
193 if (t
->variability()==kKonst
) {
194 s
+= " shape=\"box\"";
195 } else if (t
->variability()==kBlock
) {
196 s
+= " shape=\"hexagon\"";
197 } else if (t
->variability()==kSamp
) {
198 s
+= " shape=\"ellipse\"";
206 * translate signal binary operations into strings
208 static const char* binopname
[]= {
209 "+", "-", "*", "/", "%",
211 ">", "<", ">=", "<=", "==", "!=",
217 * return the label of a signal as a string
219 static string
sigLabel(Tree sig
)
223 Tree x
, y
, z
, c
, type
, name
, file
, ff
, largs
, id
, le
, sel
, var
, label
;
225 xtended
* p
= (xtended
*) getUserData(sig
);
229 if (p
) { fout
<< p
->name(); }
230 else if ( isSigInt(sig
, &i
) ) { fout
<< i
; }
231 else if ( isSigReal(sig
, &r
) ) { fout
<< r
; }
232 else if ( isSigInput(sig
, &i
) ) { fout
<< "INPUT_" << i
; }
233 else if ( isSigOutput(sig
, &i
, x
) ) { fout
<< "OUTPUT_" << i
; }
235 else if ( isSigDelay1(sig
, x
) ) { fout
<< "mem"; }
236 else if ( isSigFixDelay(sig
, x
, y
) ) { fout
<< "@"; }
237 else if ( isSigPrefix(sig
, x
, y
) ) { fout
<< "prefix"; }
238 else if ( isSigIota(sig
, x
) ) { fout
<< "iota"; }
239 else if ( isSigBinOp(sig
, &i
, x
, y
) ) { fout
<< binopname
[i
]; }
240 else if ( isSigFFun(sig
, ff
, largs
) ) { fout
<< "ffunction:" << *ff
; }
241 else if ( isSigFConst(sig
, type
, name
, file
) ) { fout
<< *name
; }
242 else if ( isSigFVar(sig
, type
, name
, file
) ) { fout
<< *name
; }
244 else if ( isSigTable(sig
, id
, x
, y
) ) { fout
<< "table:" << id
; }
245 else if ( isSigWRTbl(sig
, id
, x
, y
, z
) ) { fout
<< "write:" << id
; }
246 else if ( isSigRDTbl(sig
, x
, y
) ) { fout
<< "read"; }
250 else if ( isSigSelect2(sig
, sel
, x
, y
) ) { fout
<< "select2"; }
251 else if ( isSigSelect3(sig
, sel
, x
, y
, z
) ) { fout
<< "select3"; }
253 else if ( isSigGen(sig
, x
) ) { fout
<< "generator"; }
255 else if ( isProj(sig
, &i
, x
) ) { fout
<< "Proj" << i
; }
256 else if ( isRec(sig
, var
, le
) ) { fout
<< "REC " << *var
; }
258 else if ( isSigIntCast(sig
, x
) ) { fout
<< "int"; }
259 else if ( isSigFloatCast(sig
, x
) ) { fout
<< "float"; }
261 else if ( isSigButton(sig
, label
) ) { fout
<< "button \"" << *label
<< '"'; }
262 else if ( isSigCheckbox(sig
, label
) ) { fout
<< "checkbox \"" << *label
<< '"'; }
263 else if ( isSigVSlider(sig
, label
,c
,x
,y
,z
) ) { fout
<< "vslider \"" << *label
<< '"'; }
264 else if ( isSigHSlider(sig
, label
,c
,x
,y
,z
) ) { fout
<< "hslider \"" << *label
<< '"'; }
265 else if ( isSigNumEntry(sig
, label
,c
,x
,y
,z
) ) { fout
<< "nentry \"" << *label
<< '"'; }
267 else if ( isSigVBargraph(sig
, label
,x
,y
,z
) ) { fout
<< "vbargraph \"" << *label
<< '"'; }
268 else if ( isSigHBargraph(sig
, label
,x
,y
,z
) ) { fout
<< "hbargraph \"" << *label
<< '"'; }
270 else if ( isSigButton(sig
, label
) ) { fout
<< "button"; }
271 else if ( isSigCheckbox(sig
, label
) ) { fout
<< "checkbox"; }
272 else if ( isSigVSlider(sig
, label
,c
,x
,y
,z
) ) { fout
<< "vslider"; }
273 else if ( isSigHSlider(sig
, label
,c
,x
,y
,z
) ) { fout
<< "hslider"; }
274 else if ( isSigNumEntry(sig
, label
,c
,x
,y
,z
) ) { fout
<< "nentry"; }
276 else if ( isSigVBargraph(sig
, label
,x
,y
,z
) ) { fout
<< "vbargraph"; }
277 else if ( isSigHBargraph(sig
, label
,x
,y
,z
) ) { fout
<< "hbargraph"; }
279 else if ( isSigAttach(sig
, x
, y
) ) { fout
<< "attach"; }
281 else if ( isSigVectorize(sig
, x
, y
) ) { fout
<< "vectorize"; }
282 else if ( isSigSerialize(sig
, x
) ) { fout
<< "serialize"; }
283 else if ( isSigConcat(sig
, x
, y
) ) { fout
<< "#"; }
284 else if ( isSigVectorAt(sig
, x
, y
) ) { fout
<< "[]"; }
286 else if ( isSigUpSample(sig
, x
, y
) ) { fout
<< "up"; }
287 else if ( isSigDownSample(sig
, x
, y
) ) { fout
<< "down"; }
290 cerr
<< "ERROR in sigLabel(), unrecognized signal : " << *sig
<< endl
;