+++ /dev/null
-/************************************************************************
- ************************************************************************
- 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 <stdio.h>
-#include <iostream>
-#include <fstream>
-#include <sstream>
-#include <vector>
-#include <math.h>
-
-#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<string, int> 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<string,string>(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<string,string>(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<string,string> 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<string,string> 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<bool> used(N);
- vector<int> delay(N);
- vector<string> vname(N);
- vector<string> ctype(N);
-
- // prepare each element of a recursive definition
- for (int i=0; i<N; i++) {
- Tree e = sigProj(i,sig); // recreate each recursive definition
- if (fOccMarkup.retrieve(e)) {
- // this projection is used
- used[i] = true;
- getTypedNames(getCertifiedSigType(e), "Rec", ctype[i], vname[i]);
- setVectorNameProperty(e, vname[i]);
- delay[i] = fOccMarkup.retrieve(e)->getMaxDelay();
- } 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; i<N; i++) {
- if (used[i]) {
- generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i)));
- }
- }
-}
-
-
-/*****************************************************************************
- PREFIX, DELAY A PREFIX VALUE
-*****************************************************************************/
-
-string ScalarCompiler::generatePrefix (Tree sig, Tree x, Tree e)
-{
- Type te = getCertifiedSigType(sig);//, tEnv);
-
- string vperm = getFreshID("M");
- string vtemp = getFreshID("T");
-
- string type = cType(te);
-
- fClass->addDeclCode(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<string> args;
- vector<Type> types;
-
- for (int i=0; i<sig->arity(); 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;");
- }
-}