X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/c7f552fd8888da2f0d8cfb228fe0f28d3df3a12c..b4b6f2ea75b9f0f3ca918f5b84016610bf7a4d4f:/interpretor/faust-0.9.47mr3/compiler/generator/compile_scal.cpp diff --git a/interpretor/faust-0.9.47mr3/compiler/generator/compile_scal.cpp b/interpretor/faust-0.9.47mr3/compiler/generator/compile_scal.cpp deleted file mode 100644 index a1dfaef..0000000 --- a/interpretor/faust-0.9.47mr3/compiler/generator/compile_scal.cpp +++ /dev/null @@ -1,1290 +0,0 @@ -/************************************************************************ - ************************************************************************ - FAUST compiler - Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale - --------------------------------------------------------------------- - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ************************************************************************ - ************************************************************************/ - -/***************************************************************************** - HISTORY - 22/01/05 : corrected bug on bool signals cached in float variables -*****************************************************************************/ - - -#include "compile_scal.hh" -#include "timing.hh" - -#include "compile.hh" -#include "sigtype.hh" - -#include -#include -#include -#include -#include -#include - -#include "floats.hh" -#include "sigprint.hh" -#include "sigtyperules.hh" -#include "recursivness.hh" -#include "simplify.hh" -#include "privatise.hh" -#include "prim2.hh" -#include "xtended.hh" - -#include "compatibility.hh" -#include "ppsig.hh" -#include "sigToGraph.hh" - -using namespace std; - -extern bool gDrawSignals; -extern bool gLessTempSwitch; -extern int gMaxCopyDelay; -extern string gClassName; -extern string gMasterDocument; - -static Klass* signal2klass (const string& name, Tree sig) -{ - Type t = getCertifiedSigType(sig); //, NULLENV); - if (t->nature() == kInt) { - - ScalarCompiler C( new SigIntGenKlass(name) ); - C.compileSingleSignal(sig); - return C.getClass(); - - } else { - - ScalarCompiler C( new SigFloatGenKlass(name) ); - C.compileSingleSignal(sig); - return C.getClass(); - - } -} - - -/***************************************************************************** - getFreshID -*****************************************************************************/ - -map ScalarCompiler::fIDCounters; - -string ScalarCompiler::getFreshID(const string& prefix) -{ - if (fIDCounters.find(prefix) == fIDCounters.end()) { - fIDCounters[prefix]=0; - } - int n = fIDCounters[prefix]; - fIDCounters[prefix] = n+1; - return subst("$0$1", prefix, T(n)); -} - - -/***************************************************************************** - prepare -*****************************************************************************/ - -extern bool gDumpNorm; - -Tree ScalarCompiler::prepare(Tree LS) -{ -startTiming("ScalarCompiler::prepare"); - startTiming("deBruijn2Sym"); - Tree L1 = deBruijn2Sym(LS); // convert debruijn recursion into symbolic recursion - endTiming("deBruijn2Sym"); - Tree L2 = simplify(L1); // simplify by executing every computable operation - Tree L3 = privatise(L2); // Un-share tables with multiple writers - - // dump normal form - if (gDumpNorm) { - cout << ppsig(L3) << endl; - exit(0); - } - - recursivnessAnnotation(L3); // Annotate L3 with recursivness information - - startTiming("typeAnnotation"); - typeAnnotation(L3); // Annotate L3 with type information - endTiming("typeAnnotation"); - - sharingAnalysis(L3); // annotate L3 with sharing count - fOccMarkup.mark(L3); // annotate L3 with occurences analysis - //annotationStatistics(); -endTiming("ScalarCompiler::prepare"); - - fRates = new RateInferrer(L3); - if (gDrawSignals) { - ofstream dotfile(subst("$0-sig.dot", gMasterDocument).c_str()); - sigToGraph(L3, dotfile, fRates); - } - return L3; -} - -Tree ScalarCompiler::prepare2(Tree L0) -{ -startTiming("ScalarCompiler::prepare2"); - recursivnessAnnotation(L0); // Annotate L0 with recursivness information - typeAnnotation(L0); // Annotate L0 with type information - sharingAnalysis(L0); // annotate L0 with sharing count - fOccMarkup.mark(L0); // annotate L0 with occurences analysis -endTiming("ScalarCompiler::prepare2"); - - return L0; -} - -/***************************************************************************** - compileMultiSignal -*****************************************************************************/ - -void ScalarCompiler::compileMultiSignal (Tree L) -{ - //contextor recursivness(0); - L = prepare(L); // optimize, share and annotate expression - - for (int i = 0; i < fClass->inputs(); i++) { - fClass->addZone3(subst("$1* input$0 = input[$0];", T(i), xfloat())); - } - for (int i = 0; i < fClass->outputs(); i++) { - fClass->addZone3(subst("$1* output$0 = output[$0];", T(i), xfloat())); - } - - for (int i = 0; isList(L); L = tl(L), i++) { - Tree sig = hd(L); - fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast())); - } - generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot)); - generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot)); - if (fDescription) { - fDescription->ui(prepareUserInterfaceTree(fUIRoot)); - } -} - - -/***************************************************************************** - compileSingleSignal -*****************************************************************************/ - -void ScalarCompiler::compileSingleSignal (Tree sig) -{ - //contextor recursivness(0); - sig = prepare2(sig); // optimize and annotate expression - fClass->addExecCode(subst("output[i] = $0;", CS(sig))); - generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot)); - generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot)); - if (fDescription) { - fDescription->ui(prepareUserInterfaceTree(fUIRoot)); - } -} - - -/***************************************************************************** - CS : compile a signal -*****************************************************************************/ - -/** - * Test if a signal is already compiled - * @param sig the signal expression to compile. - * @param name the string representing the compiled expression. - * @return true is already compiled - */ -bool ScalarCompiler::getCompiledExpression(Tree sig, string& cexp) -{ - return fCompileProperty.get(sig, cexp); -} - -/** - * Set the string of a compiled expression is already compiled - * @param sig the signal expression to compile. - * @param cexp the string representing the compiled expression. - * @return the cexp (for commodity) - */ -string ScalarCompiler::setCompiledExpression(Tree sig, const string& cexp) -{ - //cerr << "ScalarCompiler::setCompiledExpression : " << cexp << " ==> " << ppsig(sig) << endl; - string old; if (fCompileProperty.get(sig, old) && (old != cexp)) { - cerr << "ERROR already a compiled expression attached : " << old << " replaced by " << cexp << endl; - exit(1); - } - fCompileProperty.set(sig, cexp); - return cexp; -} - -/** - * Compile a signal - * @param sig the signal expression to compile. - * @return the C code translation of sig as a string - */ -string ScalarCompiler::CS (Tree sig) -{ - //contextor contextRecursivness; - string code; - - if (!getCompiledExpression(sig, code)) { - // not compiled yet -/* if (getRecursivness(sig) != contextRecursivness.get()) { - contextRecursivness.set(getRecursivness(sig)); - }*/ - code = generateCode(sig); - setCompiledExpression(sig, code); - } - return code; -} - -/***************************************************************************** - generateCode : dispatch according to signal -*****************************************************************************/ -/** - * Main code generator dispatch. - * @param sig the signal expression to compile. - * @return the C code translation of sig - */ - -string ScalarCompiler::generateCode (Tree sig) -{ -#if 0 - fprintf(stderr, "CALL generateCode("); - printSignal(sig, stderr); - fprintf(stderr, ")\n"); -#endif - - int i; - double r; - Tree c, sel, x, y, z, label, id, ff, largs, type, name, file; - - //printf("compilation of %p : ", sig); print(sig); printf("\n"); - - if ( getUserData(sig) ) { return generateXtended(sig); } - else if ( isSigInt(sig, &i) ) { return generateNumber(sig, T(i)); } - else if ( isSigReal(sig, &r) ) { return generateNumber(sig, T(r)); } - else if ( isSigInput(sig, &i) ) { return generateInput (sig, T(i)); } - else if ( isSigOutput(sig, &i, x) ) { return generateOutput (sig, T(i), CS(x));} - - else if ( isSigFixDelay(sig, x, y) ) { return generateFixDelay (sig, x, y); } - else if ( isSigPrefix(sig, x, y) ) { return generatePrefix (sig, x, y); } - else if ( isSigIota(sig, x) ) { return generateIota (sig, x); } - - else if ( isSigBinOp(sig, &i, x, y) ) { return generateBinOp (sig, i, x, y); } - else if ( isSigFFun(sig, ff, largs) ) { return generateFFun (sig, ff, largs); } - else if ( isSigFConst(sig, type, name, file) ) { return generateFConst(sig, tree2str(file), tree2str(name)); } - else if ( isSigFVar(sig, type, name, file) ) { return generateFVar(sig, tree2str(file), tree2str(name)); } - - else if ( isSigTable(sig, id, x, y) ) { return generateTable (sig, x, y); } - else if ( isSigWRTbl(sig, id, x, y, z) ) { return generateWRTbl (sig, x, y, z); } - else if ( isSigRDTbl(sig, x, y) ) { return generateRDTbl (sig, x, y); } - - else if ( isSigSelect2(sig, sel, x, y) ) { return generateSelect2 (sig, sel, x, y); } - else if ( isSigSelect3(sig, sel, x, y, z) ) { return generateSelect3 (sig, sel, x, y, z); } - - else if ( isSigGen(sig, x) ) { return generateSigGen (sig, x); } - - else if ( isProj(sig, &i, x) ) { return generateRecProj (sig, x, i); } - - else if ( isSigIntCast(sig, x) ) { return generateIntCast (sig, x); } - else if ( isSigFloatCast(sig, x) ) { return generateFloatCast (sig, x); } - - else if ( isSigButton(sig, label) ) { return generateButton (sig, label); } - else if ( isSigCheckbox(sig, label) ) { return generateCheckbox (sig, label); } - else if ( isSigVSlider(sig, label,c,x,y,z) ) { return generateVSlider (sig, label, c,x,y,z); } - else if ( isSigHSlider(sig, label,c,x,y,z) ) { return generateHSlider (sig, label, c,x,y,z); } - else if ( isSigNumEntry(sig, label,c,x,y,z) ) { return generateNumEntry (sig, label, c,x,y,z); } - - else if ( isSigVBargraph(sig, label,x,y,z) ) { return generateVBargraph (sig, label, x, y, CS(z)); } - else if ( isSigHBargraph(sig, label,x,y,z) ) { return generateHBargraph (sig, label, x, y, CS(z)); } - else if ( isSigAttach(sig, x, y) ) { CS(y); return generateCacheCode(sig, CS(x)); } - - else if ( isSigUpSample(sig, x, y) ) { return generateUpSample(sig, x, y); } - else if ( isSigDownSample(sig, x, y) ) { return generateDownSample(sig, x, y); } - - - else { - printf("Error in compiling signal, unrecognized signal : "); - print(sig); - printf("\n"); - exit(1); - } - return "error in generate code"; -} - - -/***************************************************************************** - NUMBERS -*****************************************************************************/ - - -string ScalarCompiler::generateNumber (Tree sig, const string& exp) -{ - string ctype, vname; - Occurences* o = fOccMarkup.retrieve(sig); - - // check for number occuring in delays - if (o->getMaxDelay()>0) { - getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); - generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - return exp; -} - -/***************************************************************************** - FOREIGN CONSTANTS -*****************************************************************************/ - - -string ScalarCompiler::generateFConst (Tree sig, const string& file, const string& exp) -{ - string ctype, vname; - Occurences* o = fOccMarkup.retrieve(sig); - - addIncludeFile(file); - - if (o->getMaxDelay()>0) { - getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); - generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - return exp; -} - -/***************************************************************************** - FOREIGN VARIABLES -*****************************************************************************/ - - -string ScalarCompiler::generateFVar (Tree sig, const string& file, const string& exp) -{ - string ctype, vname; - - addIncludeFile(file); - return generateCacheCode(sig, exp); -} - -/***************************************************************************** - INPUTS - OUTPUTS -*****************************************************************************/ - - -string ScalarCompiler::generateInput (Tree sig, const string& idx) -{ - return generateCacheCode(sig, subst("$1input$0[i]", idx, icast())); -} - - -string ScalarCompiler::generateOutput (Tree sig, const string& idx, const string& arg) -{ - string dst = subst("output$0[i]", idx); - fClass->addExecCode(subst("$0 = $2$1;", dst, arg, xcast())); - return dst; -} - - -/***************************************************************************** - BINARY OPERATION -*****************************************************************************/ - -string ScalarCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2) -{ - return generateCacheCode(sig, subst("($0 $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2))); -} - - -/***************************************************************************** - Primitive Operations -*****************************************************************************/ - -string ScalarCompiler::generateFFun(Tree sig, Tree ff, Tree largs) -{ - addIncludeFile(ffincfile(ff)); //printf("inc file %s\n", ffincfile(ff)); - addLibrary(fflibfile(ff)); //printf("lib file %s\n", fflibfile(ff)); - - string code = ffname(ff); - code += '('; - string sep = ""; - for (int i = 0; i< ffarity(ff); i++) { - code += sep; - code += CS(nth(largs, i)); - sep = ", "; - } - code += ')'; - return generateCacheCode(sig, code); -} - - -/***************************************************************************** - CACHE CODE -*****************************************************************************/ - -void ScalarCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname) -{ - if (t->nature() == kInt) { - ctype = "int"; vname = subst("i$0", getFreshID(prefix)); - } else { - ctype = ifloat(); vname = subst("f$0", getFreshID(prefix)); - } -} - -string ScalarCompiler::generateCacheCode(Tree sig, const string& exp) -{ - string vname, ctype, code; - int sharing = getSharingCount(sig); - Occurences* o = fOccMarkup.retrieve(sig); - - // check reentrance - if (getCompiledExpression(sig, code)) { - return code; - } - - // check for expression occuring in delays - if (o->getMaxDelay()>0) { - - getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); - if (sharing>1) { - return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay()); - } else { - return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); - } - - } else if (sharing == 1) { - - return exp; - - } else if (sharing > 1) { - - return generateVariableStore(sig, exp); - - } else { - cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl; - exit(1); - } - - return "Error in generateCacheCode"; -} - - -string ScalarCompiler::generateVariableStore(Tree sig, const string& exp) -{ - string vname, ctype; - Type t = getCertifiedSigType(sig); - - switch (t->variability()) { - - case kKonst : - - getTypedNames(t, "Const", ctype, vname); - fClass->addDeclCode(subst("$0 \t$1;", ctype, vname)); - fClass->addInitCode(subst("$0 = $1;", vname, exp)); - break; - - case kBlock : - - getTypedNames(t, "Slow", ctype, vname); - fClass->addFirstPrivateDecl(vname); - fClass->addZone2(subst("$0 \t$1 = $2;", ctype, vname, exp)); - break; - - case kSamp : - - getTypedNames(t, "Temp", ctype, vname); - fClass->addExecCode(subst("$0 $1 = $2;", ctype, vname, exp)); - break; - } - return vname; -} - - -/***************************************************************************** - CASTING -*****************************************************************************/ - - -string ScalarCompiler::generateIntCast(Tree sig, Tree x) -{ - return generateCacheCode(sig, subst("int($0)", CS(x))); -} - -string ScalarCompiler::generateFloatCast (Tree sig, Tree x) -{ - return generateCacheCode(sig, subst("$1($0)", CS(x), ifloat())); -} - -/***************************************************************************** - user interface elements -*****************************************************************************/ - -string ScalarCompiler::generateButton(Tree sig, Tree path) -{ - string varname = getFreshID("fbutton"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - fClass->addInitCode(subst("$0 = 0.0;", varname)); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - return generateCacheCode(sig, varname); -} - -string ScalarCompiler::generateCheckbox(Tree sig, Tree path) -{ - string varname = getFreshID("fcheckbox"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - fClass->addInitCode(subst("$0 = 0.0;", varname)); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - return generateCacheCode(sig, varname); -} - - -string ScalarCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("fslider"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - return generateCacheCode(sig, varname); -} - -string ScalarCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("fslider"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - return generateCacheCode(sig, varname); -} - -string ScalarCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step) -{ - string varname = getFreshID("fentry"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur)))); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - return generateCacheCode(sig, varname); -} - - -string ScalarCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) -{ - string varname = getFreshID("fbargraph"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - - Type t = getCertifiedSigType(sig); - switch (t->variability()) { - - case kKonst : - fClass->addInitCode(subst("$0 = $1;", varname, exp)); - break; - - case kBlock : - fClass->addZone2(subst("$0 = $1;", varname, exp)); - break; - - case kSamp : - fClass->addExecCode(subst("$0 = $1;", varname, exp)); - break; - } - - //return varname; - return generateCacheCode(sig, varname); -} - - -string ScalarCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp) -{ - string varname = getFreshID("fbargraph"); - fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat())); - addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig)); - - Type t = getCertifiedSigType(sig); - switch (t->variability()) { - - case kKonst : - fClass->addInitCode(subst("$0 = $1;", varname, exp)); - break; - - case kBlock : - fClass->addZone2(subst("$0 = $1;", varname, exp)); - break; - - case kSamp : - fClass->addExecCode(subst("$0 = $1;", varname, exp)); - break; - } - - //return varname; - return generateCacheCode(sig, varname); -} - - - - -/***************************************************************************** - TABLES -*****************************************************************************/ - - - -/*---------------------------------------------------------------------------- - sigGen : initial table content -----------------------------------------------------------------------------*/ - -string ScalarCompiler::generateSigGen(Tree sig, Tree content) -{ - string klassname = getFreshID("SIG"); - string signame = getFreshID("sig"); - - fClass->addSubKlass(signal2klass(klassname, content)); - fClass->addInitCode(subst("$0 $1;", klassname, signame)); - fInstanceInitProperty.set(content, pair(klassname,signame)); - - return signame; -} - -string ScalarCompiler::generateStaticSigGen(Tree sig, Tree content) -{ - string klassname = getFreshID("SIG"); - string signame = getFreshID("sig"); - - fClass->addSubKlass(signal2klass(klassname, content)); - fClass->addStaticInitCode(subst("$0 $1;", klassname, signame)); - fStaticInitProperty.set(content, pair(klassname,signame)); - - return signame; -} - - -/*---------------------------------------------------------------------------- - sigTable : table declaration -----------------------------------------------------------------------------*/ - -string ScalarCompiler::generateTable(Tree sig, Tree tsize, Tree content) -{ - string generator(CS(content)); - Tree g; - string cexp; - string ctype, vname; - int size; - - // already compiled but check if we need to add declarations - - assert ( isSigGen(content, g) ); - pair kvnames; - if ( ! fInstanceInitProperty.get(g, kvnames)) { - // not declared here, we add a declaration - bool b = fStaticInitProperty.get(g, kvnames); - assert(b); - fClass->addInitCode(subst("$0 $1;", kvnames.first, kvnames.second)); - } - - if (!isSigInt(tsize, &size)) { - //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1); - cerr << "error in ScalarCompiler::generateTable() : " - << *tsize - << " is not a constant integer table size expression " - << endl; - exit(1); - } - // definition du nom et du type de la table - // A REVOIR !!!!!!!!! - Type t = getCertifiedSigType(content);//, tEnv); - if (t->nature() == kInt) { - vname = getFreshID("itbl"); - ctype = "int"; - } else { - vname = getFreshID("ftbl"); - ctype = ifloat(); - } - - // declaration de la table - fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(size))); - - // initialisation du generateur de contenu - fClass->addInitCode(subst("$0.init(samplingFreq);", generator)); - // remplissage de la table - fClass->addInitCode(subst("$0.fill($1,$2);", generator, T(size), vname)); - - // on retourne le nom de la table - return vname; -} - -string ScalarCompiler::generateStaticTable(Tree sig, Tree tsize, Tree content) -{ - //string generator(CS(content)); - Tree g; - string cexp; - string ctype, vname; - int size; - - assert ( isSigGen(content, g) ); - - if (!getCompiledExpression(content, cexp)) { - cexp = setCompiledExpression(content, generateStaticSigGen(content, g)); - } else { - // already compiled but check if we need to add declarations - pair kvnames; - if ( ! fStaticInitProperty.get(g, kvnames)) { - // not declared here, we add a declaration - bool b = fInstanceInitProperty.get(g, kvnames); - assert(b); - fClass->addStaticInitCode(subst("$0 $1;", kvnames.first, kvnames.second)); - } - } - - if (!isSigInt(tsize, &size)) { - //fprintf(stderr, "error in ScalarCompiler::generateTable()\n"); exit(1); - cerr << "error in ScalarCompiler::generateTable() : " - << *tsize - << " is not a constant integer table size expression " - << endl; - exit(1); - } - // definition du nom et du type de la table - // A REVOIR !!!!!!!!! - Type t = getCertifiedSigType(content);//, tEnv); - if (t->nature() == kInt) { - vname = getFreshID("itbl"); - ctype = "int"; - } else { - vname = getFreshID("ftbl"); - ctype = ifloat(); - } - - // declaration de la table - fClass->addDeclCode(subst("static $0 \t$1[$2];", ctype, vname, T(size))); - fClass->addStaticFields(subst("$0 \t$1::$2[$3];", ctype, fClass->getClassName(), vname, T(size) )); - - // initialisation du generateur de contenu - fClass->addStaticInitCode(subst("$0.init(samplingFreq);", cexp)); - // remplissage de la table - fClass->addStaticInitCode(subst("$0.fill($1,$2);", cexp, T(size), vname)); - - // on retourne le nom de la table - return vname; -} - - -/*---------------------------------------------------------------------------- - sigWRTable : table assignement -----------------------------------------------------------------------------*/ - -string ScalarCompiler::generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data) -{ - string tblName(CS(tbl)); - fClass->addExecCode(subst("$0[$1] = $2;", tblName, CS(idx), CS(data))); - return tblName; -} - - -/*---------------------------------------------------------------------------- - sigRDTable : table access -----------------------------------------------------------------------------*/ - -string ScalarCompiler::generateRDTbl(Tree sig, Tree tbl, Tree idx) -{ - // YO le 21/04/05 : La lecture des tables n'�ait pas mise dans le cache - // et donc le code �ait dupliqu�(dans tester.dsp par exemple) - //return subst("$0[$1]", CS(tEnv, tbl), CS(tEnv, idx)); - - //cerr << "generateRDTable " << *sig << endl; - // test the special case of a read only table that can be compiled - // has a static member - Tree id, size, content; - if( isSigTable(tbl, id, size, content) ) { - string tblname; - if (!getCompiledExpression(tbl, tblname)) { - tblname = setCompiledExpression(tbl, generateStaticTable(tbl, size, content)); - } - return generateCacheCode(sig, subst("$0[$1]", tblname, CS(idx))); - } else { - return generateCacheCode(sig, subst("$0[$1]", CS(tbl), CS(idx))); - } -} - - - -/***************************************************************************** - RECURSIONS -*****************************************************************************/ - - -/** - * Generate code for a projection of a group of mutually recursive definitions - */ -string ScalarCompiler::generateRecProj(Tree sig, Tree r, int i) -{ - string vname; - Tree var, le; - - if ( ! getVectorNameProperty(sig, vname)) { - assert(isRec(r, var, le)); - generateRec(r, var, le); - assert(getVectorNameProperty(sig, vname)); - } - return "[[UNUSED EXP]]"; // make sure the resulting expression is never used in the generated code -} - - -/** - * Generate code for a group of mutually recursive definitions - */ -void ScalarCompiler::generateRec(Tree sig, Tree var, Tree le) -{ - int N = len(le); - - vector used(N); - vector delay(N); - vector vname(N); - vector ctype(N); - - // prepare each element of a recursive definition - for (int i=0; igetMaxDelay(); - } else { - // this projection is not used therefore - // we should not generate code for it - used[i] = false; - } - } - - // generate delayline for each element of a recursive definition - for (int i=0; iaddDeclCode(subst("$0 \t$1;", type, vperm)); - fClass->addInitCode(subst("$0 = $1;", vperm, CS(x))); - - fClass->addExecCode(subst("$0 $1 = $2;", type, vtemp, vperm)); - fClass->addExecCode(subst("$0 = $1;", vperm, CS(e))); - return vtemp; -} - - -/***************************************************************************** - IOTA(n) -*****************************************************************************/ -static bool isPowerOf2(int n) -{ - return !(n & (n - 1)); -} - -string ScalarCompiler::generateIota (Tree sig, Tree n) -{ - int size; - if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); } - - string vperm = getFreshID("iota"); - - fClass->addDeclCode(subst("int \t$0;", vperm)); - fClass->addInitCode(subst("$0 = 0;", vperm)); - - if (isPowerOf2(size)) { - fClass->addExecCode(subst("$0 = ($0+1)&$1;", vperm, T(size-1))); - } else { - fClass->addExecCode(subst("if (++$0 == $1) $0=0;", vperm, T(size))); - } - return vperm; -} - - - -// a revoir en utilisant la lecture de table et en partageant la construction de la paire de valeurs - - -/** - * Generate a select2 code - */ - -string ScalarCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2) -{ - return generateCacheCode(sig, subst( "(($0)?$1:$2)", CS(sel), CS(s2), CS(s1) ) ); -} - - -/** - * Generate a select3 code (using if-then-else) - * ((int n = sel==0)? s0 : ((sel==1)? s1 : s2)) - * int nn; ((nn=sel) ? ((nn==1)? s1 : s2) : s0); - */ -string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3) -{ - return generateCacheCode(sig, subst( "(($0==0)? $1 : (($0==1)?$2:$3) )", CS(sel), CS(s1), CS(s2), CS(s3) ) ); -} - -#if 0 -string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3) -{ - Type t = getCertifiedSigType(sig); - Type t1 = getCertifiedSigType(s1); - Type t2 = getCertifiedSigType(s2); - Type t3 = getCertifiedSigType(s3); - Type w = min(t1,min(t2,t3)); - - string type = cType(t); - string var = getFreshID("S"); - - switch (w->variability()) - { - case kKonst : - fClass->addDeclCode(subst("$0 \t$1[3];", type, var)); - break; - case kBlock : - //fClass->addLocalDecl(type, subst("$0[3]", var)); - //fClass->addLocalVecDecl(type, var, 3); - fClass->addSharedDecl(var); - fClass->addZone1(subst("$0 \t$1[3];", type, var)); - break; - case kSamp : - fClass->addExecCode(subst("$0 \t$1[3];", type, var)); - break; - } - - switch (t1->variability()) - { - case kKonst : - fClass->addInitCode(subst("$0[0] = $1;", var, CS(s1))); - break; - case kBlock : - fClass->addZone2b(subst("$0[0] = $1;", var, CS(s1))); - break; - case kSamp : - fClass->addExecCode(subst("$0[0] = $1;", var, CS(s1))); - break; - } - - switch (t2->variability()) - { - case kKonst : - fClass->addInitCode(subst("$0[1] = $1;", var, CS(s2))); - break; - case kBlock : - fClass->addZone2b(subst("$0[1] = $1;", var, CS(s2))); - break; - case kSamp : - fClass->addExecCode(subst("$0[1] = $1;", var, CS(s2))); - break; - } - - switch (t3->variability()) - { - case kKonst : - fClass->addInitCode(subst("$0[2] = $1;", var, CS(s3))); - break; - case kBlock : - fClass->addZone2b(subst("$0[2] = $1;", var, CS(s3))); - break; - case kSamp : - fClass->addExecCode(subst("$0[2] = $1;", var, CS(s3))); - break; - } - - return generateCacheCode(sig, subst("$0[$1]", var, CS(sel))); -} -#endif - -/** - * retrieve the type annotation of sig - * @param sig the signal we want to know the type - */ -string ScalarCompiler::generateXtended (Tree sig) -{ - xtended* p = (xtended*) getUserData(sig); - vector args; - vector types; - - for (int i=0; iarity(); i++) { - args.push_back(CS(sig->branch(i))); - types.push_back(getCertifiedSigType(sig->branch(i))); - } - - if (p->needCache()) { - return generateCacheCode(sig, p->generateCode(fClass, args, types)); - } else { - return p->generateCode(fClass, args, types); - } -} - - - -//------------------------------------------------------------------------------------------------ - - -/***************************************************************************** - vector name property -*****************************************************************************/ - -/** - * Set the vector name property of a signal, the name of the vector used to - * store the previous values of the signal to implement a delay. - * @param sig the signal expression. - * @param vecname the string representing the vector name. - * @return true is already compiled - */ -void ScalarCompiler::setVectorNameProperty(Tree sig, const string& vecname) -{ - fVectorProperty.set(sig, vecname); -} - - -/** - * Get the vector name property of a signal, the name of the vector used to - * store the previous values of the signal to implement a delay. - * @param sig the signal expression. - * @param vecname the string where to store the vector name. - * @return true if the signal has this property, false otherwise - */ - -bool ScalarCompiler::getVectorNameProperty(Tree sig, string& vecname) -{ - return fVectorProperty.get(sig, vecname); -} - - -/** - * Compute the minimal power of 2 greater than x - */ - -int ScalarCompiler::pow2limit(int x) -{ - int n = 2; - while (n < x) { n = 2*n; } - return n; -} - -/***************************************************************************** - N-SAMPLE FIXED DELAY : sig = exp@delay - - case 1-sample max delay : - Y(t-0) Y(t-1) - Temp Var gLessTempSwitch = false - V[0] V[1] gLessTempSwitch = true - - case max delay < gMaxCopyDelay : - Y(t-0) Y(t-1) Y(t-2) ... - Temp V[0] V[1] ... gLessTempSwitch = false - V[0] V[1] V[2] ... gLessTempSwitch = true - - case max delay >= gMaxCopyDelay : - Y(t-0) Y(t-1) Y(t-2) ... - Temp V[0] V[1] ... - V[0] V[1] V[2] ... - - -*****************************************************************************/ - -/** - * Generate code for accessing a delayed signal. The generated code depend of - * the maximum delay attached to exp and the gLessTempSwitch. - */ - -string ScalarCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay) -{ - int mxd, d; - string vecname; - - //cerr << "ScalarCompiler::generateFixDelay sig = " << *sig << endl; - //cerr << "ScalarCompiler::generateFixDelay exp = " << *exp << endl; - //cerr << "ScalarCompiler::generateFixDelay del = " << *delay << endl; - - CS(exp); // ensure exp is compiled to have a vector name - - mxd = fOccMarkup.retrieve(exp)->getMaxDelay(); - - if (! getVectorNameProperty(exp, vecname)) { - cerr << "No vector name for : " << ppsig(exp) << endl; - assert(0); - } - - if (mxd == 0) { - // not a real vector name but a scalar name - return vecname; - - } else if (mxd < gMaxCopyDelay) { - if (isSigInt(delay, &d)) { - return subst("$0[$1]", vecname, CS(delay)); - } else { - return generateCacheCode(sig, subst("$0[$1]", vecname, CS(delay))); - } - - } else { - - // long delay : we use a ring buffer of size 2^x - int N = pow2limit( mxd+1 ); - return generateCacheCode(sig, subst("$0[(IOTA-$1)&$2]", vecname, CS(delay), T(N-1))); - } -} - - -/** - * Generate code for the delay mecchanism. The generated code depend of the - * maximum delay attached to exp and the "less temporaries" switch - */ - -string ScalarCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) -{ - string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd); - if (getCertifiedSigType(sig)->variability() < kSamp) { - return exp; - } else { - return s; - } -} - -/** - * Generate code for the delay mecchanism without using temporary variables - */ - -string ScalarCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) -{ - assert(mxd > 0); - - //bool odocc = fOccMarkup.retrieve(sig)->hasOutDelayOccurences(); - - if (mxd < gMaxCopyDelay) { - - // short delay : we copy - fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1))); - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1))); - fClass->addExecCode(subst("$0[0] = $1;", vname, exp)); - - // generate post processing copy code to update delay values - if (mxd == 1) { - fClass->addPostCode(subst("$0[1] = $0[0];", vname)); - } else if (mxd == 2) { - //fClass->addPostCode(subst("$0[2] = $0[1];", vname)); - fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname)); - } else { - fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname)); - } - setVectorNameProperty(sig, vname); - return subst("$0[0]", vname); - - } else { - - // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd - int N = pow2limit(mxd+1); - - // we need a iota index - ensureIotaCode(); - - // declare and init - fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N))); - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N))); - - // execute - fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp)); - setVectorNameProperty(sig, vname); - return subst("$0[IOTA&$1]", vname, T(N-1)); - } -} - -/** - * Generate code for the delay mecchanism without using temporary variables - */ - -void ScalarCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp) -{ - //assert(mxd > 0); - if (mxd == 0) { - // cerr << "MXD==0 : " << vname << " := " << exp << endl; - // no need for a real vector - fClass->addExecCode(subst("$0 \t$1 = $2;", ctype, vname, exp)); - - - } else if (mxd < gMaxCopyDelay) { - // cerr << "small delay : " << vname << "[" << mxd << "]" << endl; - - // short delay : we copy - fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1))); - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1))); - fClass->addExecCode(subst("$0[0] = $1;", vname, exp)); - - // generate post processing copy code to update delay values - if (mxd == 1) { - fClass->addPostCode(subst("$0[1] = $0[0];", vname)); - } else if (mxd == 2) { - fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname)); - } else { - fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname)); - } - - } else { - - // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd - int N = pow2limit(mxd+1); - - // we need a iota index - ensureIotaCode(); - - // declare and init - fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N))); - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N))); - - // execute - fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp)); - } -} - -/** - * Generate up sampling code - */ - -string ScalarCompiler::generateUpSample(Tree sig, Tree w, Tree x) -{ - return CS(x); -} - -/** - * Generate down sampling code - */ - -string ScalarCompiler::generateDownSample(Tree sig, Tree w, Tree x) -{ - return CS(x); -} - - -/** - * Generate code for a unique IOTA variable increased at each sample - * and used to index ring buffers. - */ -void ScalarCompiler::ensureIotaCode() -{ - if (!fHasIota) { - fHasIota = true; - fClass->addDeclCode("int \tIOTA;"); - fClass->addInitCode("IOTA = 0;"); - fClass->addPostCode("IOTA = IOTA+1;"); - } -}