X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpretor/preprocessor/faust-0.9.47mr3/compiler/generator/compile_vect.cpp diff --git a/interpretor/preprocessor/faust-0.9.47mr3/compiler/generator/compile_vect.cpp b/interpretor/preprocessor/faust-0.9.47mr3/compiler/generator/compile_vect.cpp deleted file mode 100644 index ad5b04f..0000000 --- a/interpretor/preprocessor/faust-0.9.47mr3/compiler/generator/compile_vect.cpp +++ /dev/null @@ -1,522 +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. - ************************************************************************ - ************************************************************************/ - - - -#include "compile_vect.hh" -#include "floats.hh" -#include "ppsig.hh" - -extern int gVecSize; - -void VectorCompiler::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][index];", T(i), xfloat())); - } - for (int i = 0; i < fClass->outputs(); i++) { - fClass->addZone3(subst("$1* output$0 = &output[$0][index];", T(i), xfloat())); - } - - fClass->addSharedDecl("fullcount"); - fClass->addSharedDecl("input"); - fClass->addSharedDecl("output"); - - for (int i = 0; isList(L); L = tl(L), i++) { - Tree sig = hd(L); - fClass->openLoop("count"); - fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast())); - fClass->closeLoop(sig); - } - - generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot)); - generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot)); - if (fDescription) { - fDescription->ui(prepareUserInterfaceTree(fUIRoot)); - } -} - - -/** - * Compile a signal - * @param sig the signal expression to compile. - * @return the C code translation of sig as a string - */ -string VectorCompiler::CS (Tree sig) -{ - string code; - //cerr << "ENTER VectorCompiler::CS : "<< ppsig(sig) << endl; - if (!getCompiledExpression(sig, code)) { - code = generateCode(sig); - //cerr << "CS : " << code << " for " << ppsig(sig) << endl; - setCompiledExpression(sig, code); - } else { - // we require an already compiled expression - // therefore we must update the dependencies of - // the current loop - int i; - Tree x, d, r; - Loop* ls; - Loop* tl = fClass->topLoop(); - - if (fClass->getLoopProperty(sig,ls)) { - // sig has a loop property - //cerr << "CASE SH : fBackwardLoopDependencies.insert : " << tl << " --depend(A)son--> " << ls << endl; - tl->fBackwardLoopDependencies.insert(ls); - - } else if (isSigFixDelay(sig, x, d) && fClass->getLoopProperty(x,ls)) { - //cerr << "CASE DL : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl; - tl->fBackwardLoopDependencies.insert(ls); - - } else if (isSigFixDelay(sig, x, d) && isProj(x, &i, r) && fClass->getLoopProperty(r,ls)) { - //cerr << "CASE DR : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl; - tl->fBackwardLoopDependencies.insert(ls); - - } else if (isProj(sig, &i, r) && fClass->getLoopProperty(r,ls)) { - //cerr << "CASE R* : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl; - tl->fBackwardLoopDependencies.insert(ls); - - } else { - if (isProj(sig, &i, r)) { - //cerr << "SYMBOL RECURSIF EN COURS ??? " << *r << endl; - } else if (getCertifiedSigType(sig)->variability() " << code << endl; - return code; -} - -string VectorCompiler::generateCode (Tree sig) -{ - generateCodeRecursions(sig); - return generateCodeNonRec(sig); -} - -void VectorCompiler::generateCodeRecursions (Tree sig) -{ - Tree id, body; - string code; - //cerr << "VectorCompiler::generateCodeRecursions( " << ppsig(sig) << " )" << endl; - if (getCompiledExpression(sig, code)) { - //cerr << "** ALREADY VISITED : " << code << " ===> " << ppsig(sig) << endl; - return; - } else if( isRec(sig, id, body) ) { - //cerr << "we have a recursive expression non compiled yet : " << ppsig(sig) << endl; - setCompiledExpression(sig, "[RecursionVisited]"); - fClass->openLoop(sig, "count"); - generateRec(sig, id, body); - fClass->closeLoop(sig); - } else { - // we go down the expression - vector subsigs; - int n = getSubSignals(sig, subsigs, false); - for (int i=0; itopLoop(); - assert(l); - //cerr << "VectorCompiler::OLDgenerateCode " << ppsig(sig) << endl; - if (needSeparateLoop(sig)) { - // we need a separate loop unless it's an old recursion - if (isProj(sig, &i, x)) { - // projection of a recursive group x - if (l->hasRecDependencyIn(singleton(x))) { - // x is already in the loop stack - return ScalarCompiler::generateCode(sig); - } else { - // x must be defined - fClass->openLoop(x, "count"); - string c = ScalarCompiler::generateCode(sig); - fClass->closeLoop(sig); - return c; - } - } else { - fClass->openLoop("count"); - string c = ScalarCompiler::generateCode(sig); - fClass->closeLoop(sig); - return c; - } - } else { - return ScalarCompiler::generateCode(sig); - } -} - - -/** - * Generate cache code for a signal if needed - * @param sig the signal expression. - * @param exp the corresponding C code. - * @return the cached C code - */ -string VectorCompiler::generateCacheCode(Tree sig, const string& exp) -{ - string vname, ctype; - int sharing = getSharingCount(sig); - Type t = getCertifiedSigType(sig); - Occurences* o = fOccMarkup.retrieve(sig); - int d = o->getMaxDelay(); - - if (t->variability() < kSamp) { - if (d==0) { - // non-sample, not delayed : same as scalar cache - return ScalarCompiler::generateCacheCode(sig,exp); - - } else { - // it is a non-sample expressions but used delayed - // we need a delay line - getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); - if ((sharing > 1) && !verySimple(sig)) { - // first cache this expression because it - // it is shared and complex - string cachedexp = generateVariableStore(sig, exp); - generateDelayLine(ctype, vname, d, cachedexp); - setVectorNameProperty(sig, vname); - return cachedexp; - } else { - // no need to cache this expression because - // it is either not shared or very simple - generateDelayLine(ctype, vname, d, exp); - setVectorNameProperty(sig, vname); - return exp; - } - } - } else { - // sample-rate signal - if (d > 0) { - // used delayed : we need a delay line - getTypedNames(getCertifiedSigType(sig), "Yec", ctype, vname); - generateDelayLine(ctype, vname, d, exp); - setVectorNameProperty(sig, vname); - - if (verySimple(sig)) { - return exp; - } else { - if (d < gMaxCopyDelay) { - return subst("$0[i]", vname); - } else { - // we use a ring buffer - string mask = T(pow2limit(d + gVecSize)-1); - return subst("$0[($0_idx+i) & $1]", vname, mask); - } - } - } else { - // not delayed - if ( sharing > 1 && ! verySimple(sig) ) { - // shared and not simple : we need a vector - // cerr << "ZEC : " << ppsig(sig) << endl; - getTypedNames(getCertifiedSigType(sig), "Zec", ctype, vname); - generateDelayLine(ctype, vname, d, exp); - setVectorNameProperty(sig, vname); - return subst("$0[i]", vname); - } else { - // not shared or simple : no cache needed - return exp; - } - } - } -} - -/** - * Test if a signal need to be compiled in a separate loop. - * @param sig the signal expression to test. - * @return true if a separate loop is needed - */ -bool VectorCompiler::needSeparateLoop(Tree sig) -{ - Occurences* o = fOccMarkup.retrieve(sig); - Type t = getCertifiedSigType(sig); - int c = getSharingCount(sig); - bool b; - - int i; - Tree x,y; - - - if (o->getMaxDelay()>0) { - //cerr << "DLY "; // delayed expressions require a separate loop - b = true; - } else if (verySimple(sig) || t->variability() 1) { - //cerr << "SHA(" << c << ") "; // expressions used several times required a separate loop - b = true; - } else { - // sample expressions that are not recursive, not delayed - // and not shared, doesn't require a separate loop. - b = false; - } -/* if (b) { - cerr << "Separate Loop for " << ppsig(sig) << endl; - } else { - cerr << "Same Loop for " << ppsig(sig) << endl; - }*/ - return b; -} - -void VectorCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp) -{ - if (mxd == 0) { - vectorLoop(ctype, vname, exp); - } else { - dlineLoop(ctype, vname, mxd, exp); - } -} - -string VectorCompiler::generateVariableStore(Tree sig, const string& exp) -{ - Type t = getCertifiedSigType(sig); - - if (getCertifiedSigType(sig)->variability() == kSamp) { - string vname, ctype; - getTypedNames(t, "Vector", ctype, vname); - vectorLoop(ctype, vname, exp); - return subst("$0[i]", vname); - } else { - return ScalarCompiler::generateVariableStore(sig, exp); - } -} - - -/** - * Generate code for accessing a delayed signal. The generated code depend of - * the maximum delay attached to exp and the gLessTempSwitch. - */ - -string VectorCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay) -{ - int mxd, d; - string vecname; - - //cerr << "VectorCompiler::generateFixDelay " << ppsig(sig) << endl; - - CS(exp); // ensure exp is compiled to have a vector name - - mxd = fOccMarkup.retrieve(exp)->getMaxDelay(); - - if (! getVectorNameProperty(exp, vecname)) { - cerr << "ERROR no vector name for " << ppsig(exp) << endl; - exit(1); - } - - if (mxd == 0) { - // not a real vector name but a scalar name - return subst("$0[i]", vecname); - - } else if (mxd < gMaxCopyDelay){ - if (isSigInt(delay, &d)) { - if (d == 0) { - return subst("$0[i]", vecname); - } else { - return subst("$0[i-$1]", vecname, T(d)); - } - } else { - return subst("$0[i-$1]", vecname, CS(delay)); - } - - } else { - - // long delay : we use a ring buffer of size 2^x - int N = pow2limit( mxd+gVecSize ); - - if (isSigInt(delay, &d)) { - if (d == 0) { - return subst("$0[($0_idx+i)&$1]", vecname, T(N-1)); - } else { - return subst("$0[($0_idx+i-$2)&$1]", vecname, T(N-1), T(d)); - } - } else { - return subst("$0[($0_idx+i-$2)&$1]", vecname, T(N-1), CS(delay)); - } - } -} - - -/** - * Generate code for the delay mecchanism. The generated code depend of the - * maximum delay attached to exp and the "less temporaries" switch - */ - -string VectorCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd) -{ - // it is a non-sample but used delayed - // we need a delay line - generateDelayLine(ctype, vname, mxd, exp); - setVectorNameProperty(sig, vname); - if (verySimple(sig)) { - return exp; - } else { - return subst("$0[i]", vname); - } -} - -#if 0 -static int pow2limit(int x) -{ - int n = 2; - while (n < x) { n = 2*n; } - return n; -} -#endif - -/** - * Generate the code for a (short) delay line - * @param k the c++ class where the delay line will be placed. - * @param l the loop where the code will be placed. - * @param tname the name of the C++ type (float or int) - * @param dlname the name of the delay line (vector) to be used. - * @param delay the maximum delay - * @param cexp the content of the signal as a C++ expression - */ -void VectorCompiler::vectorLoop (const string& tname, const string& vecname, const string& cexp) -{ - // -- declare the vector - fClass->addSharedDecl(vecname); - - // -- variables moved as class fields... - fClass->addZone1(subst("$0 \t$1[$2];", tname, vecname, T(gVecSize))); - - // -- compute the new samples - fClass->addExecCode(subst("$0[i] = $1;", vecname, cexp)); -} - - -/** - * Generate the code for a (short) delay line - * @param k the c++ class where the delay line will be placed. - * @param l the loop where the code will be placed. - * @param tname the name of the C++ type (float or int) - * @param dlname the name of the delay line (vector) to be used. - * @param delay the maximum delay - * @param cexp the content of the signal as a C++ expression - */ -void VectorCompiler::dlineLoop (const string& tname, const string& dlname, int delay, const string& cexp) -{ - if (delay < gMaxCopyDelay) { - - // Implementation of a copy based delayline - - // create names for temporary and permanent storage - string buf = subst("$0_tmp", dlname); - string pmem= subst("$0_perm", dlname); - - // constraints delay size to be multiple of 4 - delay = (delay+3)&-4; - - // allocate permanent storage for delayed samples - string dsize = T(delay); - fClass->addDeclCode(subst("$0 \t$1[$2];", tname, pmem, dsize)); - - // init permanent memory - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", pmem, dsize)); - - // compute method - - // -- declare a buffer and a "shifted" vector - fClass->addSharedDecl(buf); - - // -- variables moved as class fields... - fClass->addZone1(subst("$0 \t$1[$2+$3];", tname, buf, T(gVecSize), dsize)); - - fClass->addFirstPrivateDecl(dlname); - fClass->addZone2(subst("$0* \t$1 = &$2[$3];", tname, dlname, buf, dsize)); - - // -- copy the stored samples to the delay line - fClass->addPreCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[i];", buf, pmem, dsize)); - - // -- compute the new samples - fClass->addExecCode(subst("$0[i] = $1;", dlname, cexp)); - - // -- copy back to stored samples - fClass->addPostCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[count+i];", pmem, buf, dsize)); - - } else { - - // Implementation of a ring-buffer delayline - - // the size should be large enough and aligned on a power of two - delay = pow2limit(delay + gVecSize); - string dsize = T(delay); - string mask = T(delay-1); - - // create names for temporary and permanent storage - string idx = subst("$0_idx", dlname); - string idx_save = subst("$0_idx_save", dlname); - - // allocate permanent storage for delayed samples - fClass->addDeclCode(subst("$0 \t$1[$2];", tname, dlname, dsize)); - fClass->addDeclCode(subst("int \t$0;", idx)); - fClass->addDeclCode(subst("int \t$0;", idx_save)); - - // init permanent memory - fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", dlname, dsize)); - fClass->addInitCode(subst("$0 = 0;", idx)); - fClass->addInitCode(subst("$0 = 0;", idx_save)); - - // -- update index - fClass->addPreCode(subst("$0 = ($0+$1)&$2;", idx, idx_save, mask)); - - // -- compute the new samples - fClass->addExecCode(subst("$0[($2+i)&$3] = $1;", dlname, cexp, idx, mask)); - - // -- save index - fClass->addPostCode(subst("$0 = count;", idx_save)); - } -} -