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 ************************************************************************/
24 #include "propagate.hh"
34 //extern bool gPrintDocSwitch;
35 //static siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig);
38 ////////////////////////////////////////////////////////////////////////
40 * propagate : box listOfSignal-> listOfSignal'
42 * Propage une liste de signaux de l'entrée vers la sortie d'une boite
43 * La boite a été annotée aec son type
45 ///////////////////////////////////////////////////////////////////////
48 //! mix une liste de signaux sur n bus
49 siglist
mix(const siglist
& lsig
, int nbus
)
51 int nlines
= lsig
.size();
55 for (int b
=0; b
<nbus
; b
++) {
56 Tree t
= (b
<nlines
) ? lsig
[b
] : sigInt(0);
57 for (int i
=b
+nbus
; i
<nlines
; i
+=nbus
) {
58 t
= sigAdd(t
, lsig
[i
]);
65 //! split une liste de signaux sur n bus
66 siglist
split(const siglist
& inputs
, int nbus
)
68 int nlines
= inputs
.size();
70 siglist
outputs(nbus
);
72 for (int b
=0; b
<nbus
; b
++) {
73 outputs
[b
] = inputs
[b
% nlines
];
78 //! Fabrique une liste de n projections d'un groupe récursif
79 siglist
makeSigProjList (Tree t
, int n
)
82 for (int i
= 0; i
< n
; i
++) l
[i
] = sigDelay0(sigProj(i
, t
));
86 //! Fabrique une liste de n mem projections d'un groupe récursif
87 siglist
makeMemSigProjList (Tree t
, int n
)
90 for (int i
= 0; i
< n
; i
++) l
[i
] = sigDelay1(sigProj(i
, t
));
95 //! Fabrique une liste de n entrées
96 siglist
makeSigInputList (int n
)
99 for (int i
= 0; i
< n
; i
++) l
[i
] = sigInput(i
);
103 inline siglist
makeList(Tree t
)
110 siglist
listRange(const siglist
& l
, int i
, int j
)
113 for (int x
= i
; x
< j
; x
++) r
[x
-i
] = l
[x
];
117 siglist
listConcat(const siglist
& a
, const siglist
& b
)
123 for (int x
=0; x
<n1
; x
++) r
[x
] = a
[x
];
124 for (int x
=0; x
<n2
; x
++) r
[x
+n1
] = b
[x
];
129 * Convert an stl list of signals into a tree list of signals
131 Tree
listConvert(const siglist
& a
)
135 while (n
--) t
= cons(a
[n
],t
);
139 // siglist listConvertBack(Tree l)
142 // while (!isNil(l)) { r.push_back(hd(l)); l = tl(l); }
146 siglist
listLift(const siglist
& l
)
151 for(int i
= 0; i
<n
; i
++) r
[i
] = lift(l
[i
]);
155 static int gDummyInput
= 10000;
158 * Propagate computes the outputs signals of a block-diagram according to a list of input signals.
160 *\param slotenv input signals associated with symbolic slots
161 *\param path stack of user interface groups : (type,label)*
162 *\param box block-diagram where we propagate the signals
163 *\param lsig list of signals to be propagated into box
164 *\return list of resulting signals
167 // for debugging purposes
169 siglist realpropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig);
171 siglist propagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
173 cerr << "propagate in " << boxpp(box) << endl;
174 for (int i=0; i<lsig.size(); i++) { cerr << " -> signal " << i << " : " << *(lsig[i]) << endl; }
176 return realpropagate (slotenv, path, box, lsig);
181 * Old try for names propagation.
183 //siglist propagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
185 // siglist S = realPropagate(slotenv, path, box, lsig);
187 // if (gPrintDocSwitch) {
189 // if (lsig.size()==0 && getDefNameProperty(box, id)) {
190 // string nickname = defName2NickName(tree2str(id));
191 // //setSigListNickName(S, nickname);
198 //siglist realPropagate (Tree slotenv, Tree path, Tree box, const siglist& lsig)
199 siglist
propagate (Tree slotenv
, Tree path
, Tree box
, const siglist
& lsig
)
210 Tree t1
, t2
, ff
, label
, cur
, min
, max
, step
, type
, name
, file
, slot
, body
;
213 xtended
* xt
= (xtended
*)getUserData(box
);
215 // Extended Primitives
218 assert(lsig
.size() == xt
->arity());
219 return makeList(xt
->computeSigOutput(lsig
));
222 // Numbers and Constants
224 else if (isBoxInt(box
, &i
)) {
225 assert(lsig
.size()==0);
226 return makeList(sigInt(i
));
228 else if (isBoxReal(box
, &r
)) {
229 assert(lsig
.size()==0);
230 return makeList(sigReal(r
));
233 else if (isBoxFConst(box
, type
, name
, file
)) {
234 assert(lsig
.size()==0);
235 return makeList(sigFConst(type
, name
, file
));
238 else if (isBoxFVar(box
, type
, name
, file
)) {
239 assert(lsig
.size()==0);
240 return makeList(sigFVar(type
, name
, file
));
245 else if (isBoxCut(box
)) {
246 assert(lsig
.size()==1);
250 else if (isBoxWire(box
)) {
251 assert(lsig
.size()==1);
255 // Slots and Symbolic Boxes
257 else if (isBoxSlot(box
)) {
259 assert(lsig
.size()==0);
260 if (!searchEnv(box
,sig
,slotenv
)) {
261 // test YO simplification des diagrames
262 //fprintf(stderr, "propagate : internal error (slot undefined)\n");
264 sig
= sigInput(++gDummyInput
);
266 return makeList(sig
);
269 else if (isBoxSymbolic(box
, slot
, body
)) {
270 assert(lsig
.size()>0);
271 return propagate(pushEnv(slot
,lsig
[0],slotenv
), path
, body
, listRange(lsig
, 1, lsig
.size()));
276 else if (isBoxPrim0(box
, &p0
)) {
277 assert(lsig
.size()==0);
278 return makeList( p0() );
281 else if (isBoxPrim1(box
, &p1
)) {
282 assert(lsig
.size()==1);
283 return makeList( p1(lsig
[0]) );
286 else if (isBoxPrim2(box
, &p2
)) {
287 // printf("prim2 recoit : "); print(lsig); printf("\n");
288 assert(lsig
.size()==2);
289 return makeList( p2(lsig
[0],lsig
[1]) );
292 else if (isBoxPrim3(box
, &p3
)) {
293 assert(lsig
.size()==3);
294 return makeList( p3(lsig
[0],lsig
[1],lsig
[2]) );
297 else if (isBoxPrim4(box
, &p4
)) {
298 assert(lsig
.size()==4);
299 return makeList( p4(lsig
[0],lsig
[1],lsig
[2],lsig
[3]) );
302 else if (isBoxPrim5(box
, &p5
)) {
303 assert(lsig
.size()==5);
304 return makeList( p5(lsig
[0],lsig
[1],lsig
[2],lsig
[3],lsig
[4]) );
307 else if (isBoxFFun(box
, ff
)) {
308 //cerr << "propagate en boxFFun of arity " << ffarity(ff) << endl;
309 assert(int(lsig
.size())==ffarity(ff
));
310 return makeList(sigFFun(ff
, listConvert(lsig
)));
313 // User Interface Widgets
315 else if (isBoxButton(box
, label
)) {
316 assert(lsig
.size()==0);
317 return makeList(sigButton(normalizePath(cons(label
, path
))));
320 else if (isBoxCheckbox(box
, label
)) {
321 assert(lsig
.size()==0);
322 return makeList(sigCheckbox(normalizePath(cons(label
, path
))));
325 else if (isBoxVSlider(box
, label
, cur
, min
, max
, step
)) {
326 assert(lsig
.size()==0);
327 return makeList(sigVSlider(normalizePath(cons(label
, path
)), cur
, min
, max
, step
));
330 else if (isBoxHSlider(box
, label
, cur
, min
, max
, step
)) {
331 assert(lsig
.size()==0);
332 return makeList(sigHSlider(normalizePath(cons(label
, path
)), cur
, min
, max
, step
));
335 else if (isBoxNumEntry(box
, label
, cur
, min
, max
, step
)) {
336 assert(lsig
.size()==0);
337 return makeList(sigNumEntry(normalizePath(cons(label
, path
)), cur
, min
, max
, step
));
340 else if (isBoxVBargraph(box
, label
, min
, max
)) {
341 assert(lsig
.size()==1);
342 return makeList(sigVBargraph(normalizePath(cons(label
, path
)), min
, max
, lsig
[0]));
345 else if (isBoxHBargraph(box
, label
, min
, max
)) {
346 assert(lsig
.size()==1);
347 return makeList(sigHBargraph(normalizePath(cons(label
, path
)), min
, max
, lsig
[0]));
350 // User Interface Groups
352 else if (isBoxVGroup(box
, label
, t1
)) {
353 return propagate(slotenv
,cons(cons(tree(0),label
), path
), t1
, lsig
);
356 else if (isBoxHGroup(box
, label
, t1
)) {
357 return propagate(slotenv
, cons(cons(tree(1),label
), path
), t1
, lsig
);
360 else if (isBoxTGroup(box
, label
, t1
)) {
361 return propagate(slotenv
, cons(cons(tree(2),label
), path
), t1
, lsig
);
364 // Block Diagram Composition Algebra
366 else if (isBoxSeq(box
, t1
, t2
)) {
367 int in1
, out1
, in2
, out2
;
368 getBoxType(t1
, &in1
, &out1
);
369 getBoxType(t2
, &in2
, &out2
);
374 return propagate(slotenv
, path
, t2
, propagate(slotenv
, path
,t1
,lsig
));
375 } else if (out1
> in2
) {
376 siglist lr
= propagate(slotenv
, path
, t1
,lsig
);
377 return listConcat(propagate(slotenv
, path
, t2
, listRange(lr
, 0, in2
)), listRange(lr
, in2
, out1
));
379 return propagate(slotenv
, path
, t2
, listConcat( propagate(slotenv
, path
, t1
, listRange(lsig
,0,in1
)), listRange(lsig
,in1
,in1
+in2
-out1
) ) );
383 else if (isBoxPar(box
, t1
, t2
)) {
384 int in1
, out1
, in2
, out2
;
385 getBoxType(t1
, &in1
, &out1
);
386 getBoxType(t2
, &in2
, &out2
);
388 return listConcat( propagate(slotenv
, path
, t1
, listRange(lsig
, 0, in1
)),
389 propagate(slotenv
, path
, t2
, listRange(lsig
, in1
, in1
+in2
)) );
392 else if (isBoxSplit(box
, t1
, t2
)) {
393 int in1
, out1
, in2
, out2
;
394 getBoxType(t1
, &in1
, &out1
);
395 getBoxType(t2
, &in2
, &out2
);
397 siglist l1
= propagate(slotenv
, path
, t1
, lsig
);
398 siglist l2
= split(l1
, in2
);
399 return propagate(slotenv
, path
, t2
, l2
);
402 else if (isBoxMerge(box
, t1
, t2
)) {
403 int in1
, out1
, in2
, out2
;
404 getBoxType(t1
, &in1
, &out1
);
405 getBoxType(t2
, &in2
, &out2
);
407 siglist l1
= propagate(slotenv
, path
, t1
, lsig
);
408 siglist l2
= mix(l1
, in2
);
409 return propagate(slotenv
, path
, t2
, l2
);
412 else if (isBoxRec(box, t1, t2)) {
413 int in1, out1, in2, out2;
414 getBoxType(t1, &in1, &out1);
415 getBoxType(t2, &in2, &out2);
417 siglist l0 = makeSigProjList(ref(1), in2);
418 siglist l1 = propagate(slotenv, path, t2, l0);
419 siglist l2 = propagate(slotenv, path, t1, listConcat(l1,listLift(lsig)));
420 Tree g = rec(listConvert(l2));
421 return makeSigProjList(g, out1);
424 else if (isBoxRec(box
, t1
, t2
)) {
426 int in1
, out1
, in2
, out2
;
427 getBoxType(t1
, &in1
, &out1
);
428 getBoxType(t2
, &in2
, &out2
);
430 Tree slotenv2
= lift(slotenv
); // the environment must also be lifted
432 siglist l0
= makeMemSigProjList(ref(1), in2
);
433 siglist l1
= propagate(slotenv2
, path
, t2
, l0
);
434 siglist l2
= propagate(slotenv2
, path
, t1
, listConcat(l1
,listLift(lsig
)));
435 Tree g
= rec(listConvert(l2
));
436 return makeSigProjList(g
, out1
);
439 cout
<< "ERROR in file " << __FILE__
<< ':' << __LINE__
<< ", unrecognised box expression : " << boxpp(box
) << endl
;
445 Tree
boxPropagateSig (Tree path
, Tree box
, const siglist
& lsig
)
447 return listConvert(propagate(nil
, path
, box
, lsig
));