FAUST compiler  0.9.9.6b8
compile_scal.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ************************************************************************
3  FAUST compiler
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.
10 
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.
15 
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  ************************************************************************/
21 
22 /*****************************************************************************
23  HISTORY
24  22/01/05 : corrected bug on bool signals cached in float variables
25 *****************************************************************************/
26 
27 
28 #include "compile_scal.hh"
29 #include "timing.hh"
30 
31 #include "compile.hh"
32 #include "sigtype.hh"
33 
34 #include <stdio.h>
35 #include <iostream>
36 #include <fstream>
37 #include <sstream>
38 #include <vector>
39 #include <math.h>
40 
41 #include "floats.hh"
42 #include "sigprint.hh"
43 #include "sigtyperules.hh"
44 #include "recursivness.hh"
45 #include "simplify.hh"
46 #include "privatise.hh"
47 #include "prim2.hh"
48 #include "xtended.hh"
49 
50 #include "compatibility.hh"
51 #include "ppsig.hh"
52 #include "sigToGraph.hh"
53 
54 using namespace std;
55 
56 extern bool gInPlace;
57 extern bool gDrawSignals;
58 extern bool gLessTempSwitch;
59 extern int gMaxCopyDelay;
60 extern string gClassName;
61 extern string gMasterDocument;
62 
63 string makeDrawPath();
64 
65 static Klass* signal2klass (Klass* parent, const string& name, Tree sig)
66 {
67  Type t = getCertifiedSigType(sig); //, NULLENV);
68  if (t->nature() == kInt) {
69 
70  ScalarCompiler C( new SigIntGenKlass(parent, name) );
71  C.compileSingleSignal(sig);
72  return C.getClass();
73 
74  } else {
75 
76  ScalarCompiler C( new SigFloatGenKlass(parent, name) );
77  C.compileSingleSignal(sig);
78  return C.getClass();
79 
80  }
81 }
82 
83 
84 /*****************************************************************************
85  getFreshID
86 *****************************************************************************/
87 
88 map<string, int> ScalarCompiler::fIDCounters;
89 
90 string ScalarCompiler::getFreshID(const string& prefix)
91 {
92  if (fIDCounters.find(prefix) == fIDCounters.end()) {
93  fIDCounters[prefix]=0;
94  }
95  int n = fIDCounters[prefix];
96  fIDCounters[prefix] = n+1;
97  return subst("$0$1", prefix, T(n));
98 }
99 
100 
101 /*****************************************************************************
102  prepare
103 *****************************************************************************/
104 
105 extern bool gDumpNorm;
106 
108 {
109 startTiming("ScalarCompiler::prepare");
110  startTiming("deBruijn2Sym");
111  Tree L1 = deBruijn2Sym(LS); // convert debruijn recursion into symbolic recursion
112  endTiming("deBruijn2Sym");
113  Tree L2 = simplify(L1); // simplify by executing every computable operation
114  Tree L3 = privatise(L2); // Un-share tables with multiple writers
115 
116  // dump normal form
117  if (gDumpNorm) {
118  cout << ppsig(L3) << endl;
119  exit(0);
120  }
121 
122  recursivnessAnnotation(L3); // Annotate L3 with recursivness information
123 
124  startTiming("typeAnnotation");
125  typeAnnotation(L3); // Annotate L3 with type information
126  endTiming("typeAnnotation");
127 
128  sharingAnalysis(L3); // annotate L3 with sharing count
129  fOccMarkup.mark(L3); // annotate L3 with occurences analysis
130  //annotationStatistics();
131 endTiming("ScalarCompiler::prepare");
132 
133  if (gDrawSignals) {
134  ofstream dotfile(subst("$0-sig.dot", makeDrawPath()).c_str());
135  sigToGraph(L3, dotfile);
136  }
137  return L3;
138 }
139 
141 {
142 startTiming("ScalarCompiler::prepare2");
143  recursivnessAnnotation(L0); // Annotate L0 with recursivness information
144  typeAnnotation(L0); // Annotate L0 with type information
145  sharingAnalysis(L0); // annotate L0 with sharing count
146  fOccMarkup.mark(L0); // annotate L0 with occurences analysis
147 endTiming("ScalarCompiler::prepare2");
148 
149  return L0;
150 }
151 
152 /*****************************************************************************
153  compileMultiSignal
154 *****************************************************************************/
155 
157 {
158  //contextor recursivness(0);
159  L = prepare(L); // optimize, share and annotate expression
160 
161  for (int i = 0; i < fClass->inputs(); i++) {
162  fClass->addZone3(subst("$1* input$0 = input[$0];", T(i), xfloat()));
163  if (gInPlace) {
164  CS(sigInput(i));
165  }
166  }
167  for (int i = 0; i < fClass->outputs(); i++) {
168  fClass->addZone3(subst("$1* output$0 = output[$0];", T(i), xfloat()));
169  }
170 
171  for (int i = 0; isList(L); L = tl(L), i++) {
172  Tree sig = hd(L);
173  fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast()));
174  }
175  generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
176  generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
177  if (fDescription) {
178  fDescription->ui(prepareUserInterfaceTree(fUIRoot));
179  }
180 }
181 
182 
183 /*****************************************************************************
184  compileSingleSignal
185 *****************************************************************************/
186 
188 {
189  //contextor recursivness(0);
190  sig = prepare2(sig); // optimize and annotate expression
191  fClass->addExecCode(subst("output[i] = $0;", CS(sig)));
192  generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
193  generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
194  if (fDescription) {
195  fDescription->ui(prepareUserInterfaceTree(fUIRoot));
196  }
197 }
198 
199 
200 /*****************************************************************************
201  CS : compile a signal
202 *****************************************************************************/
203 
211 {
212  return fCompileProperty.get(sig, cexp);
213 }
214 
221 string ScalarCompiler::setCompiledExpression(Tree sig, const string& cexp)
222 {
223  //cerr << "ScalarCompiler::setCompiledExpression : " << cexp << " ==> " << ppsig(sig) << endl;
224  string old; if (fCompileProperty.get(sig, old) && (old != cexp)) {
225  cerr << "ERROR already a compiled expression attached : " << old << " replaced by " << cexp << endl;
226  exit(1);
227  }
228  fCompileProperty.set(sig, cexp);
229  return cexp;
230 }
231 
238 {
239  //contextor contextRecursivness;
240  string code;
241 
242  if (!getCompiledExpression(sig, code)) {
243  // not compiled yet
244 /* if (getRecursivness(sig) != contextRecursivness.get()) {
245  contextRecursivness.set(getRecursivness(sig));
246  }*/
247  code = generateCode(sig);
248  setCompiledExpression(sig, code);
249  }
250  return code;
251 }
252 
253 /*****************************************************************************
254  generateCode : dispatch according to signal
255 *****************************************************************************/
263 {
264 #if 0
265  fprintf(stderr, "CALL generateCode(");
266  printSignal(sig, stderr);
267  fprintf(stderr, ")\n");
268 #endif
269 
270  int i;
271  double r;
272  Tree c, sel, x, y, z, label, id, ff, largs, type, name, file;
273 
274  //printf("compilation of %p : ", sig); print(sig); printf("\n");
275 
276  if ( getUserData(sig) ) { return generateXtended(sig); }
277  else if ( isSigInt(sig, &i) ) { return generateNumber(sig, T(i)); }
278  else if ( isSigReal(sig, &r) ) { return generateNumber(sig, T(r)); }
279  else if ( isSigWaveform(sig) ) { return generateWaveform(sig); }
280  else if ( isSigInput(sig, &i) ) { return generateInput (sig, T(i)); }
281  else if ( isSigOutput(sig, &i, x) ) { return generateOutput (sig, T(i), CS(x));}
282 
283  else if ( isSigFixDelay(sig, x, y) ) { return generateFixDelay (sig, x, y); }
284  else if ( isSigPrefix(sig, x, y) ) { return generatePrefix (sig, x, y); }
285  else if ( isSigIota(sig, x) ) { return generateIota (sig, x); }
286 
287  else if ( isSigBinOp(sig, &i, x, y) ) { return generateBinOp (sig, i, x, y); }
288  else if ( isSigFFun(sig, ff, largs) ) { return generateFFun (sig, ff, largs); }
289  else if ( isSigFConst(sig, type, name, file) ) { return generateFConst(sig, tree2str(file), tree2str(name)); }
290  else if ( isSigFVar(sig, type, name, file) ) { return generateFVar(sig, tree2str(file), tree2str(name)); }
291 
292  else if ( isSigTable(sig, id, x, y) ) { return generateTable (sig, x, y); }
293  else if ( isSigWRTbl(sig, id, x, y, z) ) { return generateWRTbl (sig, x, y, z); }
294  else if ( isSigRDTbl(sig, x, y) ) { return generateRDTbl (sig, x, y); }
295 
296  else if ( isSigSelect2(sig, sel, x, y) ) { return generateSelect2 (sig, sel, x, y); }
297  else if ( isSigSelect3(sig, sel, x, y, z) ) { return generateSelect3 (sig, sel, x, y, z); }
298 
299  else if ( isSigGen(sig, x) ) { return generateSigGen (sig, x); }
300 
301  else if ( isProj(sig, &i, x) ) { return generateRecProj (sig, x, i); }
302 
303  else if ( isSigIntCast(sig, x) ) { return generateIntCast (sig, x); }
304  else if ( isSigFloatCast(sig, x) ) { return generateFloatCast (sig, x); }
305 
306  else if ( isSigButton(sig, label) ) { return generateButton (sig, label); }
307  else if ( isSigCheckbox(sig, label) ) { return generateCheckbox (sig, label); }
308  else if ( isSigVSlider(sig, label,c,x,y,z) ) { return generateVSlider (sig, label, c,x,y,z); }
309  else if ( isSigHSlider(sig, label,c,x,y,z) ) { return generateHSlider (sig, label, c,x,y,z); }
310  else if ( isSigNumEntry(sig, label,c,x,y,z) ) { return generateNumEntry (sig, label, c,x,y,z); }
311 
312  else if ( isSigVBargraph(sig, label,x,y,z) ) { return generateVBargraph (sig, label, x, y, CS(z)); }
313  else if ( isSigHBargraph(sig, label,x,y,z) ) { return generateHBargraph (sig, label, x, y, CS(z)); }
314  else if ( isSigAttach(sig, x, y) ) { CS(y); return generateCacheCode(sig, CS(x)); }
315 
316  else {
317  printf("Error in compiling signal, unrecognized signal : ");
318  print(sig);
319  printf("\n");
320  exit(1);
321  }
322  return "error in generate code";
323 }
324 
325 
326 /*****************************************************************************
327  NUMBERS
328 *****************************************************************************/
329 
330 
331 string ScalarCompiler::generateNumber (Tree sig, const string& exp)
332 {
333  string ctype, vname;
334  Occurences* o = fOccMarkup.retrieve(sig);
335 
336  // check for number occuring in delays
337  if (o->getMaxDelay()>0) {
338  getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname);
339  generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
340  }
341  return exp;
342 }
343 
344 /*****************************************************************************
345  FOREIGN CONSTANTS
346 *****************************************************************************/
347 
348 
349 string ScalarCompiler::generateFConst (Tree sig, const string& file, const string& exp)
350 {
351  string ctype, vname;
352  Occurences* o = fOccMarkup.retrieve(sig);
353 
354  addIncludeFile(file);
355 
356  if (o->getMaxDelay()>0) {
357  getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname);
358  generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
359  }
360  return exp;
361 }
362 
363 /*****************************************************************************
364  FOREIGN VARIABLES
365 *****************************************************************************/
366 
367 
368 string ScalarCompiler::generateFVar (Tree sig, const string& file, const string& exp)
369 {
370  string ctype, vname;
371 
372  addIncludeFile(file);
373  return generateCacheCode(sig, exp);
374 }
375 
376 /*****************************************************************************
377  INPUTS - OUTPUTS
378 *****************************************************************************/
379 
380 
381 string ScalarCompiler::generateInput (Tree sig, const string& idx)
382 {
383  if (gInPlace) {
384  // inputs must be cached for in-place transformations
385  return forceCacheCode(sig, subst("$1input$0[i]", idx, icast()));
386  } else {
387  return generateCacheCode(sig, subst("$1input$0[i]", idx, icast()));
388  }
389 }
390 
391 
392 string ScalarCompiler::generateOutput (Tree sig, const string& idx, const string& arg)
393 {
394  string dst = subst("output$0[i]", idx);
395  fClass->addExecCode(subst("$0 = $2$1;", dst, arg, xcast()));
396  return dst;
397 }
398 
399 
400 /*****************************************************************************
401  BINARY OPERATION
402 *****************************************************************************/
403 
404 string ScalarCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2)
405 {
406  if (opcode == kDiv) {
407  // special handling for division, we always want a float division
408  Type t1 = getCertifiedSigType(arg1);
409  Type t2 = getCertifiedSigType(arg2);
410 
411  if (t1->nature()==kInt && t2->nature()==kInt ) {
412  return generateCacheCode(sig, subst("($3($0) $1 $3($2))", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2), ifloat()));
413  } else if (t1->nature()==kInt && t2->nature()==kReal ) {
414  return generateCacheCode(sig, subst("($3($0) $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2), ifloat()));
415  } else if (t1->nature()==kReal && t2->nature()==kInt ) {
416  return generateCacheCode(sig, subst("($0 $1 $3($2))", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2), ifloat()));
417  } else {
418  return generateCacheCode(sig, subst("($0 $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2), ifloat()));
419  }
420  } else {
421  return generateCacheCode(sig, subst("($0 $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2)));
422  }
423 }
424 
425 
426 /*****************************************************************************
427  Primitive Operations
428 *****************************************************************************/
429 
431 {
432  addIncludeFile(ffincfile(ff)); //printf("inc file %s\n", ffincfile(ff));
433  addLibrary(fflibfile(ff)); //printf("lib file %s\n", fflibfile(ff));
434 
435  string code = ffname(ff);
436  code += '(';
437  string sep = "";
438  for (int i = 0; i< ffarity(ff); i++) {
439  code += sep;
440  code += CS(nth(largs, i));
441  sep = ", ";
442  }
443  code += ')';
444  return generateCacheCode(sig, code);
445 }
446 
447 
448 /*****************************************************************************
449  CACHE CODE
450 *****************************************************************************/
451 
452 void ScalarCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname)
453 {
454  if (t->nature() == kInt) {
455  ctype = "int"; vname = subst("i$0", getFreshID(prefix));
456  } else {
457  ctype = ifloat(); vname = subst("f$0", getFreshID(prefix));
458  }
459 }
460 
461 string ScalarCompiler::generateCacheCode(Tree sig, const string& exp)
462 {
463  string vname, ctype, code;
464  int sharing = getSharingCount(sig);
465  Occurences* o = fOccMarkup.retrieve(sig);
466 
467  // check reentrance
468  if (getCompiledExpression(sig, code)) {
469  return code;
470  }
471 
472  // check for expression occuring in delays
473  if (o->getMaxDelay()>0) {
474 
475  getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname);
476  if (sharing>1) {
477  return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay());
478  } else {
479  return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
480  }
481 
482  } else if (sharing == 1) {
483 
484  return exp;
485 
486  } else if (sharing > 1) {
487 
488  return generateVariableStore(sig, exp);
489 
490  } else {
491  cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl;
492  exit(1);
493  }
494 
495  return "Error in generateCacheCode";
496 }
497 
498 // like generateCacheCode but we force caching like if sharing was always > 1
499 string ScalarCompiler::forceCacheCode(Tree sig, const string& exp)
500 {
501  string vname, ctype, code;
502  Occurences* o = fOccMarkup.retrieve(sig);
503 
504  // check reentrance
505  if (getCompiledExpression(sig, code)) {
506  return code;
507  }
508 
509  // check for expression occuring in delays
510  if (o->getMaxDelay()>0) {
511 
512  getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname);
513  return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay());
514 
515  } else {
516 
517  return generateVariableStore(sig, exp);
518 
519  }
520 }
521 
522 
523 string ScalarCompiler::generateVariableStore(Tree sig, const string& exp)
524 {
525  string vname, ctype;
526  Type t = getCertifiedSigType(sig);
527 
528  switch (t->variability()) {
529 
530  case kKonst :
531 
532  getTypedNames(t, "Const", ctype, vname);
533  fClass->addDeclCode(subst("$0 \t$1;", ctype, vname));
534  fClass->addInitCode(subst("$0 = $1;", vname, exp));
535  break;
536 
537  case kBlock :
538 
539  getTypedNames(t, "Slow", ctype, vname);
540  fClass->addFirstPrivateDecl(vname);
541  fClass->addZone2(subst("$0 \t$1 = $2;", ctype, vname, exp));
542  break;
543 
544  case kSamp :
545 
546  getTypedNames(t, "Temp", ctype, vname);
547  fClass->addExecCode(subst("$0 $1 = $2;", ctype, vname, exp));
548  break;
549  }
550  return vname;
551 }
552 
553 
554 /*****************************************************************************
555  CASTING
556 *****************************************************************************/
557 
558 
560 {
561  return generateCacheCode(sig, subst("int($0)", CS(x)));
562 }
563 
565 {
566  return generateCacheCode(sig, subst("$1($0)", CS(x), ifloat()));
567 }
568 
569 /*****************************************************************************
570  user interface elements
571 *****************************************************************************/
572 
574 {
575  string varname = getFreshID("fbutton");
576  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
577  fClass->addInitCode(subst("$0 = 0.0;", varname));
578  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
579 
580  //return generateCacheCode(sig, varname);
581  return generateCacheCode(sig, subst("$1($0)", varname, ifloat()));
582 }
583 
585 {
586  string varname = getFreshID("fcheckbox");
587  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
588  fClass->addInitCode(subst("$0 = 0.0;", varname));
589  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
590 
591  //return generateCacheCode(sig, varname);
592  return generateCacheCode(sig, subst("$1($0)", varname, ifloat()));
593 }
594 
595 
597 {
598  string varname = getFreshID("fslider");
599  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
600  fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
601  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
602 
603  //return generateCacheCode(sig, varname);
604  return generateCacheCode(sig, subst("$1($0)", varname, ifloat()));
605 }
606 
608 {
609  string varname = getFreshID("fslider");
610  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
611  fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
612  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
613 
614  //return generateCacheCode(sig, varname);
615  return generateCacheCode(sig, subst("$1($0)", varname, ifloat()));
616 }
617 
619 {
620  string varname = getFreshID("fentry");
621  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
622  fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
623  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
624 
625  //return generateCacheCode(sig, varname);
626  return generateCacheCode(sig, subst("$1($0)", varname, ifloat()));
627 }
628 
629 
630 string ScalarCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
631 {
632  string varname = getFreshID("fbargraph");
633  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
634  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
635 
636  Type t = getCertifiedSigType(sig);
637  switch (t->variability()) {
638 
639  case kKonst :
640  fClass->addInitCode(subst("$0 = $1;", varname, exp));
641  break;
642 
643  case kBlock :
644  fClass->addZone2(subst("$0 = $1;", varname, exp));
645  break;
646 
647  case kSamp :
648  fClass->addExecCode(subst("$0 = $1;", varname, exp));
649  break;
650  }
651 
652  //return varname;
653  return generateCacheCode(sig, varname);
654 }
655 
656 
657 string ScalarCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
658 {
659  string varname = getFreshID("fbargraph");
660  fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
661  addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
662 
663  Type t = getCertifiedSigType(sig);
664  switch (t->variability()) {
665 
666  case kKonst :
667  fClass->addInitCode(subst("$0 = $1;", varname, exp));
668  break;
669 
670  case kBlock :
671  fClass->addZone2(subst("$0 = $1;", varname, exp));
672  break;
673 
674  case kSamp :
675  fClass->addExecCode(subst("$0 = $1;", varname, exp));
676  break;
677  }
678 
679  //return varname;
680  return generateCacheCode(sig, varname);
681 }
682 
683 
684 
685 
686 /*****************************************************************************
687  TABLES
688 *****************************************************************************/
689 
690 
691 
692 /*----------------------------------------------------------------------------
693  sigGen : initial table content
694 ----------------------------------------------------------------------------*/
695 
697 {
698  string klassname = getFreshID("SIG");
699  string signame = getFreshID("sig");
700 
701  fClass->addSubKlass(signal2klass(fClass, klassname, content));
702  fClass->addInitCode(subst("$0 $1;", klassname, signame));
703  fInstanceInitProperty.set(content, pair<string,string>(klassname,signame));
704 
705  return signame;
706 }
707 
709 {
710  string klassname = getFreshID("SIG");
711  string signame = getFreshID("sig");
712 
713  fClass->addSubKlass(signal2klass(fClass, klassname, content));
714  fClass->addStaticInitCode(subst("$0 $1;", klassname, signame));
715  fStaticInitProperty.set(content, pair<string,string>(klassname,signame));
716 
717  return signame;
718 }
719 
720 
721 /*----------------------------------------------------------------------------
722  sigTable : table declaration
723 ----------------------------------------------------------------------------*/
724 
725 string ScalarCompiler::generateTable(Tree sig, Tree tsize, Tree content)
726 {
727  string generator(CS(content));
728  Tree g;
729  string cexp;
730  string ctype, vname;
731  int size;
732 
733  // already compiled but check if we need to add declarations
734 
735  assert ( isSigGen(content, g) );
736  pair<string,string> kvnames;
737  if ( ! fInstanceInitProperty.get(g, kvnames)) {
738  // not declared here, we add a declaration
739  bool b = fStaticInitProperty.get(g, kvnames);
740  assert(b);
741  fClass->addInitCode(subst("$0 $1;", kvnames.first, kvnames.second));
742  }
743 
744  if (!isSigInt(tsize, &size)) {
745  //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1);
746  cerr << "error in ScalarCompiler::generateTable() : "
747  << *tsize
748  << " is not a constant integer table size expression "
749  << endl;
750  exit(1);
751  }
752  // definition du nom et du type de la table
753  // A REVOIR !!!!!!!!!
754  Type t = getCertifiedSigType(content);//, tEnv);
755  if (t->nature() == kInt) {
756  vname = getFreshID("itbl");
757  ctype = "int";
758  } else {
759  vname = getFreshID("ftbl");
760  ctype = ifloat();
761  }
762 
763  // declaration de la table
764  fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(size)));
765 
766  // initialisation du generateur de contenu
767  fClass->addInitCode(subst("$0.init(samplingFreq);", generator));
768  // remplissage de la table
769  fClass->addInitCode(subst("$0.fill($1,$2);", generator, T(size), vname));
770 
771  // on retourne le nom de la table
772  return vname;
773 }
774 
776 {
777  //string generator(CS(content));
778  Tree g;
779  string cexp;
780  string ctype, vname;
781  int size;
782 
783  assert ( isSigGen(content, g) );
784 
785  if (!getCompiledExpression(content, cexp)) {
786  cexp = setCompiledExpression(content, generateStaticSigGen(content, g));
787  } else {
788  // already compiled but check if we need to add declarations
789  pair<string,string> kvnames;
790  if ( ! fStaticInitProperty.get(g, kvnames)) {
791  // not declared here, we add a declaration
792  bool b = fInstanceInitProperty.get(g, kvnames);
793  assert(b);
794  fClass->addStaticInitCode(subst("$0 $1;", kvnames.first, kvnames.second));
795  }
796  }
797 
798  if (!isSigInt(tsize, &size)) {
799  //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1);
800  cerr << "error in ScalarCompiler::generateTable() : "
801  << *tsize
802  << " is not a constant integer table size expression "
803  << endl;
804  exit(1);
805  }
806  // definition du nom et du type de la table
807  // A REVOIR !!!!!!!!!
808  Type t = getCertifiedSigType(content);//, tEnv);
809  if (t->nature() == kInt) {
810  vname = getFreshID("itbl");
811  ctype = "int";
812  } else {
813  vname = getFreshID("ftbl");
814  ctype = ifloat();
815  }
816 
817  // declaration de la table
818  fClass->addDeclCode(subst("static $0 \t$1[$2];", ctype, vname, T(size)));
819  fClass->addStaticFields(subst("$0 \t$1::$2[$3];", ctype, fClass->getClassName(), vname, T(size) ));
820 
821  // initialisation du generateur de contenu
822  fClass->addStaticInitCode(subst("$0.init(samplingFreq);", cexp));
823  // remplissage de la table
824  fClass->addStaticInitCode(subst("$0.fill($1,$2);", cexp, T(size), vname));
825 
826  // on retourne le nom de la table
827  return vname;
828 }
829 
830 
831 /*----------------------------------------------------------------------------
832  sigWRTable : table assignement
833 ----------------------------------------------------------------------------*/
834 
835 string ScalarCompiler::generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data)
836 {
837  string tblName(CS(tbl));
838  fClass->addExecCode(subst("$0[$1] = $2;", tblName, CS(idx), CS(data)));
839  return tblName;
840 }
841 
842 
843 /*----------------------------------------------------------------------------
844  sigRDTable : table access
845 ----------------------------------------------------------------------------*/
846 
848 {
849  // YO le 21/04/05 : La lecture des tables n'�ait pas mise dans le cache
850  // et donc le code �ait dupliqu�(dans tester.dsp par exemple)
851  //return subst("$0[$1]", CS(tEnv, tbl), CS(tEnv, idx));
852 
853  //cerr << "generateRDTable " << *sig << endl;
854  // test the special case of a read only table that can be compiled
855  // has a static member
856  Tree id, size, content;
857  if( isSigTable(tbl, id, size, content) ) {
858  string tblname;
859  if (!getCompiledExpression(tbl, tblname)) {
860  tblname = setCompiledExpression(tbl, generateStaticTable(tbl, size, content));
861  }
862  return generateCacheCode(sig, subst("$0[$1]", tblname, CS(idx)));
863  } else {
864  return generateCacheCode(sig, subst("$0[$1]", CS(tbl), CS(idx)));
865  }
866 }
867 
868 
869 
870 /*****************************************************************************
871  RECURSIONS
872 *****************************************************************************/
873 
874 
879 {
880  string vname;
881  Tree var, le;
882 
883  if ( ! getVectorNameProperty(sig, vname)) {
884  assert(isRec(r, var, le));
885  generateRec(r, var, le);
886  assert(getVectorNameProperty(sig, vname));
887  }
888  return "[[UNUSED EXP]]"; // make sure the resulting expression is never used in the generated code
889 }
890 
891 
896 {
897  int N = len(le);
898 
899  vector<bool> used(N);
900  vector<int> delay(N);
901  vector<string> vname(N);
902  vector<string> ctype(N);
903 
904  // prepare each element of a recursive definition
905  for (int i=0; i<N; i++) {
906  Tree e = sigProj(i,sig); // recreate each recursive definition
907  if (fOccMarkup.retrieve(e)) {
908  // this projection is used
909  used[i] = true;
910  getTypedNames(getCertifiedSigType(e), "Rec", ctype[i], vname[i]);
911  setVectorNameProperty(e, vname[i]);
912  delay[i] = fOccMarkup.retrieve(e)->getMaxDelay();
913  } else {
914  // this projection is not used therefore
915  // we should not generate code for it
916  used[i] = false;
917  }
918  }
919 
920  // generate delayline for each element of a recursive definition
921  for (int i=0; i<N; i++) {
922  if (used[i]) {
923  generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i)));
924  }
925  }
926 }
927 
928 
929 /*****************************************************************************
930  PREFIX, DELAY A PREFIX VALUE
931 *****************************************************************************/
932 
934 {
935  Type te = getCertifiedSigType(sig);//, tEnv);
936 
937  string vperm = getFreshID("M");
938  string vtemp = getFreshID("T");
939 
940  string type = cType(te);
941 
942  fClass->addDeclCode(subst("$0 \t$1;", type, vperm));
943  fClass->addInitCode(subst("$0 = $1;", vperm, CS(x)));
944 
945  fClass->addExecCode(subst("$0 $1 = $2;", type, vtemp, vperm));
946  fClass->addExecCode(subst("$0 = $1;", vperm, CS(e)));
947  return vtemp;
948 }
949 
950 
951 /*****************************************************************************
952  IOTA(n)
953 *****************************************************************************/
954 static bool isPowerOf2(int n)
955 {
956  return !(n & (n - 1));
957 }
958 
960 {
961  int size;
962  if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); }
963 
964  string vperm = getFreshID("iota");
965 
966  fClass->addDeclCode(subst("int \t$0;", vperm));
967  fClass->addInitCode(subst("$0 = 0;", vperm));
968 
969  if (isPowerOf2(size)) {
970  fClass->addExecCode(subst("$0 = ($0+1)&$1;", vperm, T(size-1)));
971  } else {
972  fClass->addExecCode(subst("if (++$0 == $1) $0=0;", vperm, T(size)));
973  }
974  return vperm;
975 }
976 
977 
978 
979 // a revoir en utilisant la lecture de table et en partageant la construction de la paire de valeurs
980 
981 
987 {
988  return generateCacheCode(sig, subst( "(($0)?$1:$2)", CS(sel), CS(s2), CS(s1) ) );
989 }
990 
991 
997 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3)
998 {
999  return generateCacheCode(sig, subst( "(($0==0)? $1 : (($0==1)?$2:$3) )", CS(sel), CS(s1), CS(s2), CS(s3) ) );
1000 }
1001 
1002 #if 0
1003 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3)
1004 {
1005  Type t = getCertifiedSigType(sig);
1006  Type t1 = getCertifiedSigType(s1);
1007  Type t2 = getCertifiedSigType(s2);
1008  Type t3 = getCertifiedSigType(s3);
1009  Type w = min(t1,min(t2,t3));
1010 
1011  string type = cType(t);
1012  string var = getFreshID("S");
1013 
1014  switch (w->variability())
1015  {
1016  case kKonst :
1017  fClass->addDeclCode(subst("$0 \t$1[3];", type, var));
1018  break;
1019  case kBlock :
1020  //fClass->addLocalDecl(type, subst("$0[3]", var));
1021  //fClass->addLocalVecDecl(type, var, 3);
1022  fClass->addSharedDecl(var);
1023  fClass->addZone1(subst("$0 \t$1[3];", type, var));
1024  break;
1025  case kSamp :
1026  fClass->addExecCode(subst("$0 \t$1[3];", type, var));
1027  break;
1028  }
1029 
1030  switch (t1->variability())
1031  {
1032  case kKonst :
1033  fClass->addInitCode(subst("$0[0] = $1;", var, CS(s1)));
1034  break;
1035  case kBlock :
1036  fClass->addZone2b(subst("$0[0] = $1;", var, CS(s1)));
1037  break;
1038  case kSamp :
1039  fClass->addExecCode(subst("$0[0] = $1;", var, CS(s1)));
1040  break;
1041  }
1042 
1043  switch (t2->variability())
1044  {
1045  case kKonst :
1046  fClass->addInitCode(subst("$0[1] = $1;", var, CS(s2)));
1047  break;
1048  case kBlock :
1049  fClass->addZone2b(subst("$0[1] = $1;", var, CS(s2)));
1050  break;
1051  case kSamp :
1052  fClass->addExecCode(subst("$0[1] = $1;", var, CS(s2)));
1053  break;
1054  }
1055 
1056  switch (t3->variability())
1057  {
1058  case kKonst :
1059  fClass->addInitCode(subst("$0[2] = $1;", var, CS(s3)));
1060  break;
1061  case kBlock :
1062  fClass->addZone2b(subst("$0[2] = $1;", var, CS(s3)));
1063  break;
1064  case kSamp :
1065  fClass->addExecCode(subst("$0[2] = $1;", var, CS(s3)));
1066  break;
1067  }
1068 
1069  return generateCacheCode(sig, subst("$0[$1]", var, CS(sel)));
1070 }
1071 #endif
1072 
1078 {
1079  xtended* p = (xtended*) getUserData(sig);
1080  vector<string> args;
1081  vector<Type> types;
1082 
1083  for (int i=0; i<sig->arity(); i++) {
1084  args.push_back(CS(sig->branch(i)));
1085  types.push_back(getCertifiedSigType(sig->branch(i)));
1086  }
1087 
1088  if (p->needCache()) {
1089  return generateCacheCode(sig, p->generateCode(fClass, args, types));
1090  } else {
1091  return p->generateCode(fClass, args, types);
1092  }
1093 }
1094 
1095 
1096 
1097 //------------------------------------------------------------------------------------------------
1098 
1099 
1100 /*****************************************************************************
1101  vector name property
1102 *****************************************************************************/
1103 
1111 void ScalarCompiler::setVectorNameProperty(Tree sig, const string& vecname)
1112 {
1113  fVectorProperty.set(sig, vecname);
1114 }
1115 
1116 
1126 {
1127  return fVectorProperty.get(sig, vecname);
1128 }
1129 
1130 
1136 {
1137  int n = 2;
1138  while (n < x) { n = 2*n; }
1139  return n;
1140 }
1141 
1142 /*****************************************************************************
1143  N-SAMPLE FIXED DELAY : sig = exp@delay
1144 
1145  case 1-sample max delay :
1146  Y(t-0) Y(t-1)
1147  Temp Var gLessTempSwitch = false
1148  V[0] V[1] gLessTempSwitch = true
1149 
1150  case max delay < gMaxCopyDelay :
1151  Y(t-0) Y(t-1) Y(t-2) ...
1152  Temp V[0] V[1] ... gLessTempSwitch = false
1153  V[0] V[1] V[2] ... gLessTempSwitch = true
1154 
1155  case max delay >= gMaxCopyDelay :
1156  Y(t-0) Y(t-1) Y(t-2) ...
1157  Temp V[0] V[1] ...
1158  V[0] V[1] V[2] ...
1159 
1160 
1161 *****************************************************************************/
1162 
1169 {
1170  int mxd, d;
1171  string vecname;
1172 
1173  //cerr << "ScalarCompiler::generateFixDelay sig = " << *sig << endl;
1174  //cerr << "ScalarCompiler::generateFixDelay exp = " << *exp << endl;
1175  //cerr << "ScalarCompiler::generateFixDelay del = " << *delay << endl;
1176 
1177  CS(exp); // ensure exp is compiled to have a vector name
1178 
1179  mxd = fOccMarkup.retrieve(exp)->getMaxDelay();
1180 
1181  if (! getVectorNameProperty(exp, vecname)) {
1182  cerr << "No vector name for : " << ppsig(exp) << endl;
1183  assert(0);
1184  }
1185 
1186  if (mxd == 0) {
1187  // not a real vector name but a scalar name
1188  return vecname;
1189 
1190  } else if (mxd < gMaxCopyDelay) {
1191  if (isSigInt(delay, &d)) {
1192  return subst("$0[$1]", vecname, CS(delay));
1193  } else {
1194  return generateCacheCode(sig, subst("$0[$1]", vecname, CS(delay)));
1195  }
1196 
1197  } else {
1198 
1199  // long delay : we use a ring buffer of size 2^x
1200  int N = pow2limit( mxd+1 );
1201  return generateCacheCode(sig, subst("$0[(IOTA-$1)&$2]", vecname, CS(delay), T(N-1)));
1202  }
1203 }
1204 
1205 
1211 string ScalarCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
1212 {
1213  string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd);
1214  if (getCertifiedSigType(sig)->variability() < kSamp) {
1215  return exp;
1216  } else {
1217  return s;
1218  }
1219 }
1220 
1225 string ScalarCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
1226 {
1227  assert(mxd > 0);
1228 
1229  //bool odocc = fOccMarkup.retrieve(sig)->hasOutDelayOccurences();
1230 
1231  if (mxd < gMaxCopyDelay) {
1232 
1233  // short delay : we copy
1234  fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1)));
1235  fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1)));
1236  fClass->addExecCode(subst("$0[0] = $1;", vname, exp));
1237 
1238  // generate post processing copy code to update delay values
1239  if (mxd == 1) {
1240  fClass->addPostCode(subst("$0[1] = $0[0];", vname));
1241  } else if (mxd == 2) {
1242  //fClass->addPostCode(subst("$0[2] = $0[1];", vname));
1243  fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname));
1244  } else {
1245  fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname));
1246  }
1247  setVectorNameProperty(sig, vname);
1248  return subst("$0[0]", vname);
1249 
1250  } else {
1251 
1252  // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd
1253  int N = pow2limit(mxd+1);
1254 
1255  // we need a iota index
1256  ensureIotaCode();
1257 
1258  // declare and init
1259  fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N)));
1260  fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N)));
1261 
1262  // execute
1263  fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp));
1264  setVectorNameProperty(sig, vname);
1265  return subst("$0[IOTA&$1]", vname, T(N-1));
1266  }
1267 }
1268 
1273 void ScalarCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp)
1274 {
1275  //assert(mxd > 0);
1276  if (mxd == 0) {
1277  // cerr << "MXD==0 : " << vname << " := " << exp << endl;
1278  // no need for a real vector
1279  fClass->addExecCode(subst("$0 \t$1 = $2;", ctype, vname, exp));
1280 
1281 
1282  } else if (mxd < gMaxCopyDelay) {
1283  // cerr << "small delay : " << vname << "[" << mxd << "]" << endl;
1284 
1285  // short delay : we copy
1286  fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1)));
1287  fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1)));
1288  fClass->addExecCode(subst("$0[0] = $1;", vname, exp));
1289 
1290  // generate post processing copy code to update delay values
1291  if (mxd == 1) {
1292  fClass->addPostCode(subst("$0[1] = $0[0];", vname));
1293  } else if (mxd == 2) {
1294  fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname));
1295  } else {
1296  fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname));
1297  }
1298 
1299  } else {
1300 
1301  // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd
1302  int N = pow2limit(mxd+1);
1303 
1304  // we need a iota index
1305  ensureIotaCode();
1306 
1307  // declare and init
1308  fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N)));
1309  fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N)));
1310 
1311  // execute
1312  fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp));
1313  }
1314 }
1315 
1321 {
1322  if (!fHasIota) {
1323  fHasIota = true;
1324  fClass->addDeclCode("int \tIOTA;");
1325  fClass->addInitCode("IOTA = 0;");
1326  fClass->addPostCode("IOTA = IOTA+1;");
1327  }
1328 }
1329 
1334 void ScalarCompiler::declareWaveform(Tree sig, string& vname, int& size)
1335 {
1336  // computes C type and unique name for the waveform
1337  string ctype;
1338  getTypedNames(getCertifiedSigType(sig), "Wave", ctype, vname);
1339 
1340  size = sig->arity();
1341 
1342  // Converts waveform into a string : "{a,b,c,...}"
1343  stringstream content;
1344 
1345  char sep = '{';
1346  for (int i = 0; i < size; i++) {
1347  content << sep << ppsig(sig->branch(i));
1348  sep = ',';
1349  }
1350  content << '}';
1351 
1352  // Declares the Waveform
1353  fClass->addDeclCode(subst("static $0 \t$1[$2];", ctype, vname, T(size)));
1354  fClass->addDeclCode(subst("int \tidx$0;", vname));
1355  fClass->addInitCode(subst("idx$0 = 0;", vname));
1356  fClass->getTopParentKlass()->addStaticFields(
1357  subst("$0 \t$1::$2[$3] = ", ctype, fClass->getFullClassName(), vname, T(size) )
1358  + content.str() + ";");
1359 }
1360 
1362 {
1363  string vname;
1364  int size;
1365 
1366  declareWaveform(sig, vname, size);
1367  fClass->addPostCode(subst("idx$0 = (idx$0 + 1) % $1;", vname, T(size)));
1368  return generateCacheCode(sig, subst("$0[idx$0]", vname));
1369 }
bool isSigHSlider(Tree s)
Definition: signals.cpp:217
bool isSigRDTbl(Tree s, Tree &t, Tree &i)
Definition: signals.cpp:77
void sigToGraph(Tree L, ofstream &fout)
Draw a list of signals as a directed graph using graphviz's dot language.
Definition: sigToGraph.cpp:50
Compile a list of FAUST signals into a scalar C++ class.
Definition: compile_scal.hh:40
void ensureIotaCode()
Generate code for a unique IOTA variable increased at each sample and used to index ring buffers...
bool isSigFConst(Tree s)
Definition: signals.cpp:138
string setCompiledExpression(Tree sig, const string &name)
Set the string of a compiled expression is already compiled.
bool isSigPrefix(Tree t, Tree &t0, Tree &t1)
Definition: signals.cpp:66
virtual string CS(Tree sig)
Compile a signal.
bool isSigCheckbox(Tree s)
Definition: signals.cpp:205
string generateHBargraph(Tree sig, Tree label, Tree min, Tree max, const string &exp)
Tree reverse(Tree l)
Definition: list.cpp:240
bool isSigFFun(Tree s, Tree &ff, Tree &largs)
Definition: signals.cpp:133
bool isSigNumEntry(Tree s)
Definition: signals.cpp:257
int gMaxCopyDelay
Definition: main.cpp:131
void getTypedNames(Type t, const string &prefix, string &ctype, string &vname)
int pow2limit(int x)
Compute the minimal power of 2 greater than x.
bool isSigSelect2(Tree t, Tree &selector, Tree &s1, Tree &s2)
Definition: signals.cpp:116
Tree deBruijn2Sym(Tree t)
bool gDumpNorm
Definition: main.cpp:149
void endTiming(const char *msg)
Definition: timing.cpp:43
Tree sigInput(int i)
Definition: signals.cpp:47
string generateSelect3(Tree sig, Tree sel, Tree s1, Tree s2, Tree s3)
Generate a select3 code (using if-then-else) ((int n = sel==0)? s0 : ((sel==1)? s1 : s2)) int nn; ((n...
bool isSigIota(Tree t, Tree &t0)
Definition: signals.cpp:70
Definition: sigtype.hh:54
virtual string generateWaveform(Tree sig)
string generatePrefix(Tree sig, Tree x, Tree e)
A CTree = (Node x [CTree]) is a Node associated with a list of subtrees called branches.
Definition: tree.hh:109
string generateSelect2(Tree sig, Tree sel, Tree s1, Tree s2)
Generate a select2 code.
const char * ffname(Tree t)
Definition: prim2.cpp:60
const char * xcast()
Definition: floats.cpp:50
void typeAnnotation(Tree sig)
Fully annotate every subtree of term with type information.
bool isSigInput(Tree t, int *i)
Definition: signals.cpp:48
Tree prepare2(Tree L0)
int ffarity(Tree t)
Definition: prim2.cpp:67
bool isSigFixDelay(Tree t, Tree &t0, Tree &t1)
Definition: signals.cpp:62
string generateSigGen(Tree sig, Tree content)
Tree simplify(Tree sig)
Definition: simplify.cpp:76
string generateHSlider(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step)
Tree hd(Tree l)
Definition: list.hh:133
const char * xfloat()
Definition: floats.cpp:49
virtual bool needCache()=0
string generateFVar(Tree sig, const string &file, const string &name)
string gClassName
Definition: main.cpp:158
bool gDrawSignals
Definition: main.cpp:116
Tree uiWidget(Tree label, Tree varname, Tree sig)
Definition: uitree.cpp:140
const char * icast()
Definition: floats.cpp:47
string generateIota(Tree sig, Tree arg)
bool isSigVBargraph(Tree s)
Definition: signals.cpp:285
bool isSigSelect3(Tree t, Tree &selector, Tree &s1, Tree &s2, Tree &s3)
Definition: signals.cpp:119
string generateRecProj(Tree sig, Tree exp, int i)
Generate code for a projection of a group of mutually recursive definitions.
bool isSigVSlider(Tree s)
Definition: signals.cpp:237
string generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2)
double max(double x, double y)
Definition: interval.hh:60
bool isSigGen(Tree t, Tree &x)
Definition: signals.cpp:91
string generateRDTbl(Tree sig, Tree tbl, Tree idx)
string generateNumEntry(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step)
string generateDelayVecNoTemp(Tree sig, const string &exp, const string &ctype, const string &vname, int mxd)
Generate code for the delay mecchanism without using temporary variables.
Definition: binop.hh:56
const char * ffincfile(Tree ff)
Definition: prim2.cpp:45
bool isSigReal(Tree t, double *r)
Definition: signals.cpp:44
string generateButton(Tree sig, Tree label)
string generateStaticTable(Tree sig, Tree tsize, Tree content)
string gMasterDocument
Definition: main.cpp:104
virtual string generateDelayVec(Tree sig, const string &exp, const string &ctype, const string &vname, int mxd)
Generate code for the delay mecchanism.
string generateFloatCast(Tree sig, Tree x)
Tree privatise(const Tree &t)
Definition: privatise.cpp:45
Tree sigProj(int i, Tree rgroup)
Definition: signals.cpp:150
bool getVectorNameProperty(Tree sig, string &vecname)
Get the vector name property of a signal, the name of the vector used to store the previous values of...
string generateVSlider(Tree sig, Tree label, Tree cur, Tree min, Tree max, Tree step)
Definition: ppsig.hh:48
string cType(Type t)
Definition: sigtype.cpp:340
bool gLessTempSwitch
Definition: main.cpp:130
string getFreshID(const string &prefix)
string subst(const string &model, const vector< string > &args)
Text substitution.
Definition: Text.cpp:47
bool isSigHBargraph(Tree s)
Definition: signals.cpp:279
Definition: klass.hh:55
bool isList(Tree l)
Definition: list.hh:138
bool getCompiledExpression(Tree sig, string &name)
Test if a signal is already compiled.
virtual string generateVariableStore(Tree sig, const string &exp)
void startTiming(const char *msg)
Definition: timing.cpp:34
bool isSigTable(Tree t, Tree &id, Tree &n, Tree &sig)
Definition: signals.cpp:85
string T(char *c)
Definition: Text.cpp:158
void printSignal(Tree sig, FILE *out, int prec)
Definition: sigprint.cpp:85
bool isSigBinOp(Tree s, int *op, Tree &x, Tree &y)
Definition: signals.cpp:126
bool isSigAttach(Tree t, Tree &t0, Tree &t1)
Definition: signals.cpp:291
string makeDrawPath()
Definition: main.cpp:177
Definition: sigtype.hh:54
Tree prepare(Tree L0)
string generateCheckbox(Tree sig, Tree label)
Definition: sigtype.hh:56
Type getCertifiedSigType(Tree sig)
Retrieve the type of sig and check it exists.
bool isSigWRTbl(Tree u, Tree &id, Tree &t, Tree &i, Tree &s)
Definition: signals.cpp:81
void recursivnessAnnotation(Tree sig)
Annotate a signal with recursivness.
int arity() const
return the number of branches (subtrees) of a tree
Definition: tree.hh:144
void generateRec(Tree sig, Tree var, Tree le)
Generate code for a group of mutually recursive definitions.
string generateInput(Tree sig, const string &idx)
const char * name(Symbol *sym)
Returns the name of a symbol.
Definition: symbol.hh:98
bool isSigWaveform(Tree s)
Definition: signals.cpp:211
string generateIntCast(Tree sig, Tree x)
string generateXtended(Tree sig)
retrieve the type annotation of sig
bool isRec(Tree t, Tree &body)
is t a de Bruijn recursive tree
bool isSigInt(Tree t, int *i)
Definition: signals.cpp:41
virtual void compileSingleSignal(Tree lsig)
Tree tree(const Node &n)
Definition: tree.hh:186
string generateOutput(Tree sig, const string &idx, const string &arg1)
static bool isPowerOf2(int n)
virtual string generateCacheCode(Tree sig, const string &exp)
string generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data)
const char * fflibfile(Tree ff)
Definition: prim2.cpp:50
string generateNumber(Tree sig, const string &exp)
virtual string generateFixDelay(Tree sig, Tree arg, Tree size)
Generate code for accessing a delayed signal.
bool isSigFloatCast(Tree t)
Definition: signals.cpp:187
virtual string generateCode(Klass *klass, const vector< string > &args, const vector< Type > &types)=0
string generateFFun(Tree sig, Tree ff, Tree largs)
int getMaxDelay() const
return the maximal delay collected
Definition: occurences.cpp:54
bool isSigFVar(Tree s)
Definition: signals.cpp:144
void * getUserData(Symbol *sym)
Returns user data.
Definition: symbol.hh:100
void declareWaveform(Tree sig, string &vname, int &size)
Generate code for a waveform.
bool isSigIntCast(Tree t)
Definition: signals.cpp:184
BinOp * gBinOpTable[]
Definition: binop.cpp:28
void setVectorNameProperty(Tree sig, const string &vecname)
Set the vector name property of a signal, the name of the vector used to store the previous values of...
virtual void compileMultiSignal(Tree lsig)
string generateFConst(Tree sig, const string &file, const string &name)
bool isProj(Tree t, int *i, Tree &rgroup)
Definition: signals.cpp:151
API to the typing system of signals.
bool gInPlace
Definition: main.cpp:163
double min(double x, double y)
Definition: interval.hh:59
double tree2float(Tree t)
if t has a node of type float, return it otherwise error
Definition: tree.cpp:246
static Klass * signal2klass(Klass *parent, const string &name, Tree sig)
int len(Tree l)
Definition: list.cpp:198
string generateVBargraph(Tree sig, Tree label, Tree min, Tree max, const string &exp)
virtual string generateCode(Tree sig)
Main code generator dispatch.
Tree tl(Tree l)
Definition: list.hh:134
const char * tree2str(Tree t)
if t has a node of type symbol, return its name otherwise error
Definition: tree.cpp:278
Tree branch(int i) const
return the ith branch (subtree) of a tree
Definition: tree.hh:145
Tree nth(Tree l, int i)
Definition: list.cpp:182
Klass * getClass()
Definition: compile.hh:67
string generateStaticSigGen(Tree sig, Tree content)
virtual void generateDelayLine(const string &ctype, const string &vname, int mxd, const string &exp)
Generate code for the delay mecchanism without using temporary variables.
bool isSigOutput(Tree t, int *i, Tree &t0)
Definition: signals.cpp:52
const char * ifloat()
Definition: floats.cpp:46
bool isSigButton(Tree s)
Definition: signals.cpp:199
string generateTable(Tree sig, Tree tsize, Tree content)
static map< string, int > fIDCounters
Definition: compile_scal.hh:48
void print(Tree t, FILE *out)
Definition: list.cpp:154
virtual string forceCacheCode(Tree sig, const string &exp)