|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 00022 /***************************************************************************** 00023 HISTORY 00024 22/01/05 : corrected bug on bool signals cached in float variables 00025 *****************************************************************************/ 00026 00027 00028 #include "compile_scal.hh" 00029 #include "timing.hh" 00030 00031 #include "compile.hh" 00032 #include "sigtype.hh" 00033 00034 #include <stdio.h> 00035 #include <iostream> 00036 #include <fstream> 00037 #include <sstream> 00038 #include <vector> 00039 #include <math.h> 00040 00041 #include "floats.hh" 00042 #include "sigprint.hh" 00043 #include "sigtyperules.hh" 00044 #include "recursivness.hh" 00045 #include "simplify.hh" 00046 #include "privatise.hh" 00047 #include "prim2.hh" 00048 #include "xtended.hh" 00049 00050 #include "compatibility.hh" 00051 #include "ppsig.hh" 00052 #include "sigToGraph.hh" 00053 00054 using namespace std; 00055 00056 extern bool gDrawSignals; 00057 extern bool gLessTempSwitch; 00058 extern int gMaxCopyDelay; 00059 extern string gClassName; 00060 extern string gMasterDocument; 00061 00062 static Klass* signal2klass (const string& name, Tree sig) 00063 { 00064 Type t = getCertifiedSigType(sig); //, NULLENV); 00065 if (t->nature() == kInt) { 00066 00067 ScalarCompiler C( new SigIntGenKlass(name) ); 00068 C.compileSingleSignal(sig); 00069 return C.getClass(); 00070 00071 } else { 00072 00073 ScalarCompiler C( new SigFloatGenKlass(name) ); 00074 C.compileSingleSignal(sig); 00075 return C.getClass(); 00076 00077 } 00078 } 00079 00080 00081 /***************************************************************************** 00082 getFreshID 00083 *****************************************************************************/ 00084 00085 map<string, int> ScalarCompiler::fIDCounters; 00086 00087 string ScalarCompiler::getFreshID(const string& prefix) 00088 { 00089 if (fIDCounters.find(prefix) == fIDCounters.end()) { 00090 fIDCounters[prefix]=0; 00091 } 00092 int n = fIDCounters[prefix]; 00093 fIDCounters[prefix] = n+1; 00094 return subst("$0$1", prefix, T(n)); 00095 } 00096 00097 00098 /***************************************************************************** 00099 prepare 00100 *****************************************************************************/ 00101 00102 extern bool gDumpNorm; 00103 00104 Tree ScalarCompiler::prepare(Tree LS) 00105 { 00106 startTiming("ScalarCompiler::prepare"); 00107 startTiming("deBruijn2Sym"); 00108 Tree L1 = deBruijn2Sym(LS); // convert debruijn recursion into symbolic recursion 00109 endTiming("deBruijn2Sym"); 00110 Tree L2 = simplify(L1); // simplify by executing every computable operation 00111 Tree L3 = privatise(L2); // Un-share tables with multiple writers 00112 00113 // dump normal form 00114 if (gDumpNorm) { 00115 cout << ppsig(L3) << endl; 00116 exit(0); 00117 } 00118 00119 recursivnessAnnotation(L3); // Annotate L3 with recursivness information 00120 00121 startTiming("typeAnnotation"); 00122 typeAnnotation(L3); // Annotate L3 with type information 00123 endTiming("typeAnnotation"); 00124 00125 sharingAnalysis(L3); // annotate L3 with sharing count 00126 fOccMarkup.mark(L3); // annotate L3 with occurences analysis 00127 //annotationStatistics(); 00128 endTiming("ScalarCompiler::prepare"); 00129 00130 if (gDrawSignals) { 00131 ofstream dotfile(subst("$0-sig.dot", gMasterDocument).c_str()); 00132 sigToGraph(L3, dotfile); 00133 } 00134 return L3; 00135 } 00136 00137 Tree ScalarCompiler::prepare2(Tree L0) 00138 { 00139 startTiming("ScalarCompiler::prepare2"); 00140 recursivnessAnnotation(L0); // Annotate L0 with recursivness information 00141 typeAnnotation(L0); // Annotate L0 with type information 00142 sharingAnalysis(L0); // annotate L0 with sharing count 00143 fOccMarkup.mark(L0); // annotate L0 with occurences analysis 00144 endTiming("ScalarCompiler::prepare2"); 00145 00146 return L0; 00147 } 00148 00149 /***************************************************************************** 00150 compileMultiSignal 00151 *****************************************************************************/ 00152 00153 void ScalarCompiler::compileMultiSignal (Tree L) 00154 { 00155 //contextor recursivness(0); 00156 L = prepare(L); // optimize, share and annotate expression 00157 00158 for (int i = 0; i < fClass->inputs(); i++) { 00159 fClass->addZone3(subst("$1* input$0 = input[$0];", T(i), xfloat())); 00160 } 00161 for (int i = 0; i < fClass->outputs(); i++) { 00162 fClass->addZone3(subst("$1* output$0 = output[$0];", T(i), xfloat())); 00163 } 00164 00165 for (int i = 0; isList(L); L = tl(L), i++) { 00166 Tree sig = hd(L); 00167 fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast())); 00168 } 00169 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot)); 00170 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot)); 00171 if (fDescription) { 00172 fDescription->ui(prepareUserInterfaceTree(fUIRoot)); 00173 } 00174 } 00175 00176 00177 /***************************************************************************** 00178 compileSingleSignal 00179 *****************************************************************************/ 00180 00181 void ScalarCompiler::compileSingleSignal (Tree sig) 00182 { 00183 //contextor recursivness(0); 00184 sig = prepare2(sig); // optimize and annotate expression 00185 fClass->addExecCode(subst("output[i] = $0;", CS(sig))); 00186 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot)); 00187 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot)); 00188 if (fDescription) { 00189 fDescription->ui(prepareUserInterfaceTree(fUIRoot)); 00190 } 00191 } 00192 00193 00194 /***************************************************************************** 00195 CS : compile a signal 00196 *****************************************************************************/ 00197 00204 bool ScalarCompiler::getCompiledExpression(Tree sig, string& cexp) 00205 { 00206 return fCompileProperty.get(sig, cexp); 00207 } 00208 00215 string ScalarCompiler::setCompiledExpression(Tree sig, const string& cexp) 00216 { 00217 //cerr << "ScalarCompiler::setCompiledExpression : " << cexp << " ==> " << ppsig(sig) << endl; 00218 string old; if (fCompileProperty.get(sig, old) && (old != cexp)) { 00219 cerr << "ERROR already a compiled expression attached : " << old << " replaced by " << cexp << endl; 00220 exit(1); 00221 } 00222 fCompileProperty.set(sig, cexp); 00223 return cexp; 00224 } 00225 00231 string ScalarCompiler::CS (Tree sig) 00232 { 00233 //contextor contextRecursivness; 00234 string code; 00235 00236 if (!getCompiledExpression(sig, code)) { 00237 // not compiled yet 00238 /* if (getRecursivness(sig) != contextRecursivness.get()) { 00239 contextRecursivness.set(getRecursivness(sig)); 00240 }*/ 00241 code = generateCode(sig); 00242 setCompiledExpression(sig, code); 00243 } 00244 return code; 00245 } 00246 00247 /***************************************************************************** 00248 generateCode : dispatch according to signal 00249 *****************************************************************************/ 00256 string ScalarCompiler::generateCode (Tree sig) 00257 { 00258 #if 0 00259 fprintf(stderr, "CALL generateCode("); 00260 printSignal(sig, stderr); 00261 fprintf(stderr, ")\n"); 00262 #endif 00263 00264 int i; 00265 double r; 00266 Tree c, sel, x, y, z, label, id, ff, largs, type, name, file; 00267 00268 //printf("compilation of %p : ", sig); print(sig); printf("\n"); 00269 00270 if ( getUserData(sig) ) { return generateXtended(sig); } 00271 else if ( isSigInt(sig, &i) ) { return generateNumber(sig, T(i)); } 00272 else if ( isSigReal(sig, &r) ) { return generateNumber(sig, T(r)); } 00273 else if ( isSigInput(sig, &i) ) { return generateInput (sig, T(i)); } 00274 else if ( isSigOutput(sig, &i, x) ) { return generateOutput (sig, T(i), CS(x));} 00275 00276 else if ( isSigFixDelay(sig, x, y) ) { return generateFixDelay (sig, x, y); } 00277 else if ( isSigPrefix(sig, x, y) ) { return generatePrefix (sig, x, y); } 00278 else if ( isSigIota(sig, x) ) { return generateIota (sig, x); } 00279 00280 else if ( isSigBinOp(sig, &i, x, y) ) { return generateBinOp (sig, i, x, y); } 00281 else if ( isSigFFun(sig, ff, largs) ) { return generateFFun (sig, ff, largs); } 00282 else if ( isSigFConst(sig, type, name, file) ) { return generateFConst(sig, tree2str(file), tree2str(name)); } 00283 else if ( isSigFVar(sig, type, name, file) ) { return generateFVar(sig, tree2str(file), tree2str(name)); } 00284 00285 else if ( isSigTable(sig, id, x, y) ) { return generateTable (sig, x, y); } 00286 else if ( isSigWRTbl(sig, id, x, y, z) ) { return generateWRTbl (sig, x, y, z); } 00287 else if ( isSigRDTbl(sig, x, y) ) { return generateRDTbl (sig, x, y); } 00288 00289 else if ( isSigSelect2(sig, sel, x, y) ) { return generateSelect2 (sig, sel, x, y); } 00290 else if ( isSigSelect3(sig, sel, x, y, z) ) { return generateSelect3 (sig, sel, x, y, z); } 00291 00292 else if ( isSigGen(sig, x) ) { return generateSigGen (sig, x); } 00293 00294 else if ( isProj(sig, &i, x) ) { return generateRecProj (sig, x, i); } 00295 00296 else if ( isSigIntCast(sig, x) ) { return generateIntCast (sig, x); } 00297 else if ( isSigFloatCast(sig, x) ) { return generateFloatCast (sig, x); } 00298 00299 else if ( isSigButton(sig, label) ) { return generateButton (sig, label); } 00300 else if ( isSigCheckbox(sig, label) ) { return generateCheckbox (sig, label); } 00301 else if ( isSigVSlider(sig, label,c,x,y,z) ) { return generateVSlider (sig, label, c,x,y,z); } 00302 else if ( isSigHSlider(sig, label,c,x,y,z) ) { return generateHSlider (sig, label, c,x,y,z); } 00303 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { return generateNumEntry (sig, label, c,x,y,z); } 00304 00305 else if ( isSigVBargraph(sig, label,x,y,z) ) { return generateVBargraph (sig, label, x, y, CS(z)); } 00306 else if ( isSigHBargraph(sig, label,x,y,z) ) { return generateHBargraph (sig, label, x, y, CS(z)); } 00307 else if ( isSigAttach(sig, x, y) ) { CS(y); return generateCacheCode(sig, CS(x)); } 00308 00309 else { 00310 printf("Error in compiling signal, unrecognized signal : "); 00311 print(sig); 00312 printf("\n"); 00313 exit(1); 00314 } 00315 return "error in generate code"; 00316 } 00317 00318 00319 /***************************************************************************** 00320 NUMBERS 00321 *****************************************************************************/ 00322 00323 00324 string ScalarCompiler::generateNumber (Tree sig, const string& exp) 00325 { 00326 string ctype, vname; 00327 Occurences* o = fOccMarkup.retrieve(sig); 00328 00329 // check for number occuring in delays 00330 if (o->getMaxDelay()>0) { 00331 getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); 00332 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); 00333 } 00334 return exp; 00335 } 00336 00337 /***************************************************************************** 00338 FOREIGN CONSTANTS 00339 *****************************************************************************/ 00340 00341 00342 string ScalarCompiler::generateFConst (Tree sig, const string& file, const string& exp) 00343 { 00344 string ctype, vname; 00345 Occurences* o = fOccMarkup.retrieve(sig); 00346 00347 addIncludeFile(file); 00348 00349 if (o->getMaxDelay()>0) { 00350 getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); 00351 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); 00352 } 00353 return exp; 00354 } 00355 00356 /***************************************************************************** 00357 FOREIGN VARIABLES 00358 *****************************************************************************/ 00359 00360 00361 string ScalarCompiler::generateFVar (Tree sig, const string& file, const string& exp) 00362 { 00363 string ctype, vname; 00364 00365 addIncludeFile(file); 00366 return generateCacheCode(sig, exp); 00367 } 00368 00369 /***************************************************************************** 00370 INPUTS - OUTPUTS 00371 *****************************************************************************/ 00372 00373 00374 string ScalarCompiler::generateInput (Tree sig, const string& idx) 00375 { 00376 return generateCacheCode(sig, subst("$1input$0[i]", idx, icast())); 00377 } 00378 00379 00380 string ScalarCompiler::generateOutput (Tree sig, const string& idx, const string& arg) 00381 { 00382 string dst = subst("output$0[i]", idx); 00383 fClass->addExecCode(subst("$0 = $2$1;", dst, arg, xcast())); 00384 return dst; 00385 } 00386 00387 00388 /***************************************************************************** 00389 BINARY OPERATION 00390 *****************************************************************************/ 00391 00392 string ScalarCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2) 00393 { 00394 return generateCacheCode(sig, subst("($0 $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2))); 00395 } 00396 00397 00398 /***************************************************************************** 00399 Primitive Operations 00400 *****************************************************************************/ 00401 00402 string ScalarCompiler::generateFFun(Tree sig, Tree ff, Tree largs) 00403 { 00404 addIncludeFile(ffincfile(ff)); //printf("inc file %s\n", ffincfile(ff)); 00405 addLibrary(fflibfile(ff)); //printf("lib file %s\n", fflibfile(ff)); 00406 00407 string code = ffname(ff); 00408 code += '('; 00409 string sep = ""; 00410 for (int i = 0; i< ffarity(ff); i++) { 00411 code += sep; 00412 code += CS(nth(largs, i)); 00413 sep = ", "; 00414 } 00415 code += ')'; 00416 return generateCacheCode(sig, code); 00417 } 00418 00419 00420 /***************************************************************************** 00421 CACHE CODE 00422 *****************************************************************************/ 00423 00424 void ScalarCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname) 00425 { 00426 if (t->nature() == kInt) { 00427 ctype = "int"; vname = subst("i$0", getFreshID(prefix)); 00428 } else { 00429 ctype = ifloat(); vname = subst("f$0", getFreshID(prefix)); 00430 } 00431 } 00432 00433 string ScalarCompiler::generateCacheCode(Tree sig, const string& exp) 00434 { 00435 string vname, ctype, code; 00436 int sharing = getSharingCount(sig); 00437 Occurences* o = fOccMarkup.retrieve(sig); 00438 00439 // check reentrance 00440 if (getCompiledExpression(sig, code)) { 00441 return code; 00442 } 00443 00444 // check for expression occuring in delays 00445 if (o->getMaxDelay()>0) { 00446 00447 getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); 00448 if (sharing>1) { 00449 return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay()); 00450 } else { 00451 return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); 00452 } 00453 00454 } else if (sharing == 1) { 00455 00456 return exp; 00457 00458 } else if (sharing > 1) { 00459 00460 return generateVariableStore(sig, exp); 00461 00462 } else { 00463 cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl; 00464 exit(1); 00465 } 00466 00467 return "Error in generateCacheCode"; 00468 } 00469 00470 00471 string ScalarCompiler::generateVariableStore(Tree sig, const string& exp) 00472 { 00473 string vname, ctype; 00474 Type t = getCertifiedSigType(sig); 00475 00476 switch (t->variability()) { 00477 00478 case kKonst : 00479 00480 getTypedNames(t, "Const", ctype, vname); 00481 fClass->addDeclCode(subst("$0 \t$1;", ctype, vname)); 00482 fClass->addInitCode(subst("$0 = $1;", vname, exp)); 00483 break; 00484 00485 case kBlock : 00486 00487 getTypedNames(t, "Slow", ctype, vname); 00488 fClass->addFirstPrivateDecl(vname); 00489 fClass->addZone2(subst("$0 \t$1 = $2;", ctype, vname, exp)); 00490 break; 00491 00492 case kSamp : 00493 00494 getTypedNames(t, "Temp", ctype, vname); 00495 fClass->addExecCode(subst("$0 $1 = $2;", ctype, vname, exp)); 00496 break; 00497 } 00498 return vname; 00499 } 00500 00501 00502 /***************************************************************************** 00503 CASTING 00504 *****************************************************************************/ 00505 00506 00507 string ScalarCompiler::generateIntCast(Tree sig, Tree x) 00508 { 00509 return generateCacheCode(sig, subst("int($0)", CS(x))); 00510 } 00511 00512 string ScalarCompiler::generateFloatCast (Tree sig, Tree x) 00513 { 00514 return generateCacheCode(sig, subst("$1($0)", CS(x), ifloat())); 00515 } 00516 00517 /***************************************************************************** 00518 user interface elements 00519 *****************************************************************************/ 00520 00521 string ScalarCompiler::generateButton(Tree sig, Tree path) 00522 { 00523 string varname = getFreshID("fbutton"); 00524 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00525 fClass->addInitCode(subst("$0 = 0.0;", varname)); 00526 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00527 return generateCacheCode(sig, varname); 00528 } 00529 00530 string ScalarCompiler::generateCheckbox(Tree sig, Tree path) 00531 { 00532 string varname = getFreshID("fcheckbox"); 00533 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00534 fClass->addInitCode(subst("$0 = 0.0;", varname)); 00535 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00536 return generateCacheCode(sig, varname); 00537 } 00538 00539 00540 string ScalarCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) 00541 { 00542 string varname = getFreshID("fslider"); 00543 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00544 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); 00545 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00546 return generateCacheCode(sig, varname); 00547 } 00548 00549 string ScalarCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) 00550 { 00551 string varname = getFreshID("fslider"); 00552 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00553 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); 00554 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00555 return generateCacheCode(sig, varname); 00556 } 00557 00558 string ScalarCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) 00559 { 00560 string varname = getFreshID("fentry"); 00561 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00562 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); 00563 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00564 return generateCacheCode(sig, varname); 00565 } 00566 00567 00568 string ScalarCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) 00569 { 00570 string varname = getFreshID("fbargraph"); 00571 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00572 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00573 00574 Type t = getCertifiedSigType(sig); 00575 switch (t->variability()) { 00576 00577 case kKonst : 00578 fClass->addInitCode(subst("$0 = $1;", varname, exp)); 00579 break; 00580 00581 case kBlock : 00582 fClass->addZone2(subst("$0 = $1;", varname, exp)); 00583 break; 00584 00585 case kSamp : 00586 fClass->addExecCode(subst("$0 = $1;", varname, exp)); 00587 break; 00588 } 00589 00590 //return varname; 00591 return generateCacheCode(sig, varname); 00592 } 00593 00594 00595 string ScalarCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) 00596 { 00597 string varname = getFreshID("fbargraph"); 00598 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); 00599 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); 00600 00601 Type t = getCertifiedSigType(sig); 00602 switch (t->variability()) { 00603 00604 case kKonst : 00605 fClass->addInitCode(subst("$0 = $1;", varname, exp)); 00606 break; 00607 00608 case kBlock : 00609 fClass->addZone2(subst("$0 = $1;", varname, exp)); 00610 break; 00611 00612 case kSamp : 00613 fClass->addExecCode(subst("$0 = $1;", varname, exp)); 00614 break; 00615 } 00616 00617 //return varname; 00618 return generateCacheCode(sig, varname); 00619 } 00620 00621 00622 00623 00624 /***************************************************************************** 00625 TABLES 00626 *****************************************************************************/ 00627 00628 00629 00630 /*---------------------------------------------------------------------------- 00631 sigGen : initial table content 00632 ----------------------------------------------------------------------------*/ 00633 00634 string ScalarCompiler::generateSigGen(Tree sig, Tree content) 00635 { 00636 string klassname = getFreshID("SIG"); 00637 string signame = getFreshID("sig"); 00638 00639 fClass->addSubKlass(signal2klass(klassname, content)); 00640 fClass->addInitCode(subst("$0 $1;", klassname, signame)); 00641 fInstanceInitProperty.set(content, pair<string,string>(klassname,signame)); 00642 00643 return signame; 00644 } 00645 00646 string ScalarCompiler::generateStaticSigGen(Tree sig, Tree content) 00647 { 00648 string klassname = getFreshID("SIG"); 00649 string signame = getFreshID("sig"); 00650 00651 fClass->addSubKlass(signal2klass(klassname, content)); 00652 fClass->addStaticInitCode(subst("$0 $1;", klassname, signame)); 00653 fStaticInitProperty.set(content, pair<string,string>(klassname,signame)); 00654 00655 return signame; 00656 } 00657 00658 00659 /*---------------------------------------------------------------------------- 00660 sigTable : table declaration 00661 ----------------------------------------------------------------------------*/ 00662 00663 string ScalarCompiler::generateTable(Tree sig, Tree tsize, Tree content) 00664 { 00665 string generator(CS(content)); 00666 Tree g; 00667 string cexp; 00668 string ctype, vname; 00669 int size; 00670 00671 // already compiled but check if we need to add declarations 00672 00673 assert ( isSigGen(content, g) ); 00674 pair<string,string> kvnames; 00675 if ( ! fInstanceInitProperty.get(g, kvnames)) { 00676 // not declared here, we add a declaration 00677 bool b = fStaticInitProperty.get(g, kvnames); 00678 assert(b); 00679 fClass->addInitCode(subst("$0 $1;", kvnames.first, kvnames.second)); 00680 } 00681 00682 if (!isSigInt(tsize, &size)) { 00683 //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1); 00684 cerr << "error in ScalarCompiler::generateTable() : " 00685 << *tsize 00686 << " is not a constant integer table size expression " 00687 << endl; 00688 exit(1); 00689 } 00690 // definition du nom et du type de la table 00691 // A REVOIR !!!!!!!!! 00692 Type t = getCertifiedSigType(content);//, tEnv); 00693 if (t->nature() == kInt) { 00694 vname = getFreshID("itbl"); 00695 ctype = "int"; 00696 } else { 00697 vname = getFreshID("ftbl"); 00698 ctype = ifloat(); 00699 } 00700 00701 // declaration de la table 00702 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(size))); 00703 00704 // initialisation du generateur de contenu 00705 fClass->addInitCode(subst("$0.init(samplingFreq);", generator)); 00706 // remplissage de la table 00707 fClass->addInitCode(subst("$0.fill($1,$2);", generator, T(size), vname)); 00708 00709 // on retourne le nom de la table 00710 return vname; 00711 } 00712 00713 string ScalarCompiler::generateStaticTable(Tree sig, Tree tsize, Tree content) 00714 { 00715 //string generator(CS(content)); 00716 Tree g; 00717 string cexp; 00718 string ctype, vname; 00719 int size; 00720 00721 assert ( isSigGen(content, g) ); 00722 00723 if (!getCompiledExpression(content, cexp)) { 00724 cexp = setCompiledExpression(content, generateStaticSigGen(content, g)); 00725 } else { 00726 // already compiled but check if we need to add declarations 00727 pair<string,string> kvnames; 00728 if ( ! fStaticInitProperty.get(g, kvnames)) { 00729 // not declared here, we add a declaration 00730 bool b = fInstanceInitProperty.get(g, kvnames); 00731 assert(b); 00732 fClass->addStaticInitCode(subst("$0 $1;", kvnames.first, kvnames.second)); 00733 } 00734 } 00735 00736 if (!isSigInt(tsize, &size)) { 00737 //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1); 00738 cerr << "error in ScalarCompiler::generateTable() : " 00739 << *tsize 00740 << " is not a constant integer table size expression " 00741 << endl; 00742 exit(1); 00743 } 00744 // definition du nom et du type de la table 00745 // A REVOIR !!!!!!!!! 00746 Type t = getCertifiedSigType(content);//, tEnv); 00747 if (t->nature() == kInt) { 00748 vname = getFreshID("itbl"); 00749 ctype = "int"; 00750 } else { 00751 vname = getFreshID("ftbl"); 00752 ctype = ifloat(); 00753 } 00754 00755 // declaration de la table 00756 fClass->addDeclCode(subst("static $0 \t$1[$2];", ctype, vname, T(size))); 00757 fClass->addStaticFields(subst("$0 \t$1::$2[$3];", ctype, fClass->getClassName(), vname, T(size) )); 00758 00759 // initialisation du generateur de contenu 00760 fClass->addStaticInitCode(subst("$0.init(samplingFreq);", cexp)); 00761 // remplissage de la table 00762 fClass->addStaticInitCode(subst("$0.fill($1,$2);", cexp, T(size), vname)); 00763 00764 // on retourne le nom de la table 00765 return vname; 00766 } 00767 00768 00769 /*---------------------------------------------------------------------------- 00770 sigWRTable : table assignement 00771 ----------------------------------------------------------------------------*/ 00772 00773 string ScalarCompiler::generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data) 00774 { 00775 string tblName(CS(tbl)); 00776 fClass->addExecCode(subst("$0[$1] = $2;", tblName, CS(idx), CS(data))); 00777 return tblName; 00778 } 00779 00780 00781 /*---------------------------------------------------------------------------- 00782 sigRDTable : table access 00783 ----------------------------------------------------------------------------*/ 00784 00785 string ScalarCompiler::generateRDTbl(Tree sig, Tree tbl, Tree idx) 00786 { 00787 // YO le 21/04/05 : La lecture des tables n'�ait pas mise dans le cache 00788 // et donc le code �ait dupliqu�(dans tester.dsp par exemple) 00789 //return subst("$0[$1]", CS(tEnv, tbl), CS(tEnv, idx)); 00790 00791 //cerr << "generateRDTable " << *sig << endl; 00792 // test the special case of a read only table that can be compiled 00793 // has a static member 00794 Tree id, size, content; 00795 if( isSigTable(tbl, id, size, content) ) { 00796 string tblname; 00797 if (!getCompiledExpression(tbl, tblname)) { 00798 tblname = setCompiledExpression(tbl, generateStaticTable(tbl, size, content)); 00799 } 00800 return generateCacheCode(sig, subst("$0[$1]", tblname, CS(idx))); 00801 } else { 00802 return generateCacheCode(sig, subst("$0[$1]", CS(tbl), CS(idx))); 00803 } 00804 } 00805 00806 00807 00808 /***************************************************************************** 00809 RECURSIONS 00810 *****************************************************************************/ 00811 00812 00816 string ScalarCompiler::generateRecProj(Tree sig, Tree r, int i) 00817 { 00818 string vname; 00819 Tree var, le; 00820 00821 if ( ! getVectorNameProperty(sig, vname)) { 00822 assert(isRec(r, var, le)); 00823 generateRec(r, var, le); 00824 assert(getVectorNameProperty(sig, vname)); 00825 } 00826 return "[[UNUSED EXP]]"; // make sure the resulting expression is never used in the generated code 00827 } 00828 00829 00833 void ScalarCompiler::generateRec(Tree sig, Tree var, Tree le) 00834 { 00835 int N = len(le); 00836 00837 vector<bool> used(N); 00838 vector<int> delay(N); 00839 vector<string> vname(N); 00840 vector<string> ctype(N); 00841 00842 // prepare each element of a recursive definition 00843 for (int i=0; i<N; i++) { 00844 Tree e = sigProj(i,sig); // recreate each recursive definition 00845 if (fOccMarkup.retrieve(e)) { 00846 // this projection is used 00847 used[i] = true; 00848 getTypedNames(getCertifiedSigType(e), "Rec", ctype[i], vname[i]); 00849 setVectorNameProperty(e, vname[i]); 00850 delay[i] = fOccMarkup.retrieve(e)->getMaxDelay(); 00851 } else { 00852 // this projection is not used therefore 00853 // we should not generate code for it 00854 used[i] = false; 00855 } 00856 } 00857 00858 // generate delayline for each element of a recursive definition 00859 for (int i=0; i<N; i++) { 00860 if (used[i]) { 00861 generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i))); 00862 } 00863 } 00864 } 00865 00866 00867 /***************************************************************************** 00868 PREFIX, DELAY A PREFIX VALUE 00869 *****************************************************************************/ 00870 00871 string ScalarCompiler::generatePrefix (Tree sig, Tree x, Tree e) 00872 { 00873 Type te = getCertifiedSigType(sig);//, tEnv); 00874 00875 string vperm = getFreshID("M"); 00876 string vtemp = getFreshID("T"); 00877 00878 string type = cType(te); 00879 00880 fClass->addDeclCode(subst("$0 \t$1;", type, vperm)); 00881 fClass->addInitCode(subst("$0 = $1;", vperm, CS(x))); 00882 00883 fClass->addExecCode(subst("$0 $1 = $2;", type, vtemp, vperm)); 00884 fClass->addExecCode(subst("$0 = $1;", vperm, CS(e))); 00885 return vtemp; 00886 } 00887 00888 00889 /***************************************************************************** 00890 IOTA(n) 00891 *****************************************************************************/ 00892 static bool isPowerOf2(int n) 00893 { 00894 return !(n & (n - 1)); 00895 } 00896 00897 string ScalarCompiler::generateIota (Tree sig, Tree n) 00898 { 00899 int size; 00900 if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); } 00901 00902 string vperm = getFreshID("iota"); 00903 00904 fClass->addDeclCode(subst("int \t$0;", vperm)); 00905 fClass->addInitCode(subst("$0 = 0;", vperm)); 00906 00907 if (isPowerOf2(size)) { 00908 fClass->addExecCode(subst("$0 = ($0+1)&$1;", vperm, T(size-1))); 00909 } else { 00910 fClass->addExecCode(subst("if (++$0 == $1) $0=0;", vperm, T(size))); 00911 } 00912 return vperm; 00913 } 00914 00915 00916 00917 // a revoir en utilisant la lecture de table et en partageant la construction de la paire de valeurs 00918 00919 00924 string ScalarCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2) 00925 { 00926 return generateCacheCode(sig, subst( "(($0)?$1:$2)", CS(sel), CS(s2), CS(s1) ) ); 00927 } 00928 00929 00935 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3) 00936 { 00937 return generateCacheCode(sig, subst( "(($0==0)? $1 : (($0==1)?$2:$3) )", CS(sel), CS(s1), CS(s2), CS(s3) ) ); 00938 } 00939 00940 #if 0 00941 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3) 00942 { 00943 Type t = getCertifiedSigType(sig); 00944 Type t1 = getCertifiedSigType(s1); 00945 Type t2 = getCertifiedSigType(s2); 00946 Type t3 = getCertifiedSigType(s3); 00947 Type w = min(t1,min(t2,t3)); 00948 00949 string type = cType(t); 00950 string var = getFreshID("S"); 00951 00952 switch (w->variability()) 00953 { 00954 case kKonst : 00955 fClass->addDeclCode(subst("$0 \t$1[3];", type, var)); 00956 break; 00957 case kBlock : 00958 //fClass->addLocalDecl(type, subst("$0[3]", var)); 00959 //fClass->addLocalVecDecl(type, var, 3); 00960 fClass->addSharedDecl(var); 00961 fClass->addZone1(subst("$0 \t$1[3];", type, var)); 00962 break; 00963 case kSamp : 00964 fClass->addExecCode(subst("$0 \t$1[3];", type, var)); 00965 break; 00966 } 00967 00968 switch (t1->variability()) 00969 { 00970 case kKonst : 00971 fClass->addInitCode(subst("$0[0] = $1;", var, CS(s1))); 00972 break; 00973 case kBlock : 00974 fClass->addZone2b(subst("$0[0] = $1;", var, CS(s1))); 00975 break; 00976 case kSamp : 00977 fClass->addExecCode(subst("$0[0] = $1;", var, CS(s1))); 00978 break; 00979 } 00980 00981 switch (t2->variability()) 00982 { 00983 case kKonst : 00984 fClass->addInitCode(subst("$0[1] = $1;", var, CS(s2))); 00985 break; 00986 case kBlock : 00987 fClass->addZone2b(subst("$0[1] = $1;", var, CS(s2))); 00988 break; 00989 case kSamp : 00990 fClass->addExecCode(subst("$0[1] = $1;", var, CS(s2))); 00991 break; 00992 } 00993 00994 switch (t3->variability()) 00995 { 00996 case kKonst : 00997 fClass->addInitCode(subst("$0[2] = $1;", var, CS(s3))); 00998 break; 00999 case kBlock : 01000 fClass->addZone2b(subst("$0[2] = $1;", var, CS(s3))); 01001 break; 01002 case kSamp : 01003 fClass->addExecCode(subst("$0[2] = $1;", var, CS(s3))); 01004 break; 01005 } 01006 01007 return generateCacheCode(sig, subst("$0[$1]", var, CS(sel))); 01008 } 01009 #endif 01010 01015 string ScalarCompiler::generateXtended (Tree sig) 01016 { 01017 xtended* p = (xtended*) getUserData(sig); 01018 vector<string> args; 01019 vector<Type> types; 01020 01021 for (int i=0; i<sig->arity(); i++) { 01022 args.push_back(CS(sig->branch(i))); 01023 types.push_back(getCertifiedSigType(sig->branch(i))); 01024 } 01025 01026 if (p->needCache()) { 01027 return generateCacheCode(sig, p->generateCode(fClass, args, types)); 01028 } else { 01029 return p->generateCode(fClass, args, types); 01030 } 01031 } 01032 01033 01034 01035 //------------------------------------------------------------------------------------------------ 01036 01037 01038 /***************************************************************************** 01039 vector name property 01040 *****************************************************************************/ 01041 01049 void ScalarCompiler::setVectorNameProperty(Tree sig, const string& vecname) 01050 { 01051 fVectorProperty.set(sig, vecname); 01052 } 01053 01054 01063 bool ScalarCompiler::getVectorNameProperty(Tree sig, string& vecname) 01064 { 01065 return fVectorProperty.get(sig, vecname); 01066 } 01067 01068 01073 int ScalarCompiler::pow2limit(int x) 01074 { 01075 int n = 2; 01076 while (n < x) { n = 2*n; } 01077 return n; 01078 } 01079 01080 /***************************************************************************** 01081 N-SAMPLE FIXED DELAY : sig = exp@delay 01082 01083 case 1-sample max delay : 01084 Y(t-0) Y(t-1) 01085 Temp Var gLessTempSwitch = false 01086 V[0] V[1] gLessTempSwitch = true 01087 01088 case max delay < gMaxCopyDelay : 01089 Y(t-0) Y(t-1) Y(t-2) ... 01090 Temp V[0] V[1] ... gLessTempSwitch = false 01091 V[0] V[1] V[2] ... gLessTempSwitch = true 01092 01093 case max delay >= gMaxCopyDelay : 01094 Y(t-0) Y(t-1) Y(t-2) ... 01095 Temp V[0] V[1] ... 01096 V[0] V[1] V[2] ... 01097 01098 01099 *****************************************************************************/ 01100 01106 string ScalarCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay) 01107 { 01108 int mxd, d; 01109 string vecname; 01110 01111 //cerr << "ScalarCompiler::generateFixDelay sig = " << *sig << endl; 01112 //cerr << "ScalarCompiler::generateFixDelay exp = " << *exp << endl; 01113 //cerr << "ScalarCompiler::generateFixDelay del = " << *delay << endl; 01114 01115 CS(exp); // ensure exp is compiled to have a vector name 01116 01117 mxd = fOccMarkup.retrieve(exp)->getMaxDelay(); 01118 01119 if (! getVectorNameProperty(exp, vecname)) { 01120 cerr << "No vector name for : " << ppsig(exp) << endl; 01121 assert(0); 01122 } 01123 01124 if (mxd == 0) { 01125 // not a real vector name but a scalar name 01126 return vecname; 01127 01128 } else if (mxd < gMaxCopyDelay) { 01129 if (isSigInt(delay, &d)) { 01130 return subst("$0[$1]", vecname, CS(delay)); 01131 } else { 01132 return generateCacheCode(sig, subst("$0[$1]", vecname, CS(delay))); 01133 } 01134 01135 } else { 01136 01137 // long delay : we use a ring buffer of size 2^x 01138 int N = pow2limit( mxd+1 ); 01139 return generateCacheCode(sig, subst("$0[(IOTA-$1)&$2]", vecname, CS(delay), T(N-1))); 01140 } 01141 } 01142 01143 01149 string ScalarCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) 01150 { 01151 string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd); 01152 if (getCertifiedSigType(sig)->variability() < kSamp) { 01153 return exp; 01154 } else { 01155 return s; 01156 } 01157 } 01158 01163 string ScalarCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) 01164 { 01165 assert(mxd > 0); 01166 01167 //bool odocc = fOccMarkup.retrieve(sig)->hasOutDelayOccurences(); 01168 01169 if (mxd < gMaxCopyDelay) { 01170 01171 // short delay : we copy 01172 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1))); 01173 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1))); 01174 fClass->addExecCode(subst("$0[0] = $1;", vname, exp)); 01175 01176 // generate post processing copy code to update delay values 01177 if (mxd == 1) { 01178 fClass->addPostCode(subst("$0[1] = $0[0];", vname)); 01179 } else if (mxd == 2) { 01180 //fClass->addPostCode(subst("$0[2] = $0[1];", vname)); 01181 fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname)); 01182 } else { 01183 fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname)); 01184 } 01185 setVectorNameProperty(sig, vname); 01186 return subst("$0[0]", vname); 01187 01188 } else { 01189 01190 // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd 01191 int N = pow2limit(mxd+1); 01192 01193 // we need a iota index 01194 ensureIotaCode(); 01195 01196 // declare and init 01197 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N))); 01198 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N))); 01199 01200 // execute 01201 fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp)); 01202 setVectorNameProperty(sig, vname); 01203 return subst("$0[IOTA&$1]", vname, T(N-1)); 01204 } 01205 } 01206 01211 void ScalarCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp) 01212 { 01213 //assert(mxd > 0); 01214 if (mxd == 0) { 01215 // cerr << "MXD==0 : " << vname << " := " << exp << endl; 01216 // no need for a real vector 01217 fClass->addExecCode(subst("$0 \t$1 = $2;", ctype, vname, exp)); 01218 01219 01220 } else if (mxd < gMaxCopyDelay) { 01221 // cerr << "small delay : " << vname << "[" << mxd << "]" << endl; 01222 01223 // short delay : we copy 01224 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1))); 01225 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1))); 01226 fClass->addExecCode(subst("$0[0] = $1;", vname, exp)); 01227 01228 // generate post processing copy code to update delay values 01229 if (mxd == 1) { 01230 fClass->addPostCode(subst("$0[1] = $0[0];", vname)); 01231 } else if (mxd == 2) { 01232 fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname)); 01233 } else { 01234 fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname)); 01235 } 01236 01237 } else { 01238 01239 // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd 01240 int N = pow2limit(mxd+1); 01241 01242 // we need a iota index 01243 ensureIotaCode(); 01244 01245 // declare and init 01246 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N))); 01247 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N))); 01248 01249 // execute 01250 fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp)); 01251 } 01252 } 01253 01258 void ScalarCompiler::ensureIotaCode() 01259 { 01260 if (!fHasIota) { 01261 fHasIota = true; 01262 fClass->addDeclCode("int \tIOTA;"); 01263 fClass->addInitCode("IOTA = 0;"); 01264 fClass->addPostCode("IOTA = IOTA+1;"); 01265 } 01266 }
1.8.0