VectorCompiler Class Reference

Compile a list of FAUST signals into a vector C++ class. More...

#include <compile_vect.hh>

Inherits ScalarCompiler.

Inherited by SchedulerCompiler.

Collaboration diagram for VectorCompiler:
[legend]

List of all members.

Public Member Functions

 VectorCompiler (const string &name, const string &super, int numInputs, int numOutputs)
 VectorCompiler (Klass *k)
virtual void compileMultiSignal (Tree L)

Protected Member Functions

virtual string CS (Tree sig)
 Compile a signal.
virtual string generateCode (Tree sig)
 Compile a signal.
virtual string generateCacheCode (Tree sig, const string &exp)
 Generate cache code for a signal if needed.
virtual void generateDelayLine (const string &ctype, const string &vname, int mxd, const string &exp)
 Generate code for the delay mecchanism without using temporary variables.
virtual string generateVariableStore (Tree sig, const string &exp)
virtual string generateFixDelay (Tree sig, Tree exp, Tree delay)
 Generate code for accessing a delayed signal.
virtual string generateDelayVec (Tree sig, const string &exp, const string &ctype, const string &vname, int mxd)
 Generate code for the delay mecchanism.
virtual void vectorLoop (const string &tname, const string &dlname, const string &cexp)
 Generate the code for a (short) delay line.
virtual void dlineLoop (const string &tname, const string &dlname, int delay, const string &cexp)
 Generate the code for a (short) delay line.
bool needSeparateLoop (Tree sig)
 Test if a signal need to be compiled in a separate loop.

Detailed Description

Compile a list of FAUST signals into a vector C++ class.

Definition at line 39 of file compile_vect.hh.


Constructor & Destructor Documentation

VectorCompiler::VectorCompiler ( const string &  name,
const string &  super,
int  numInputs,
int  numOutputs 
) [inline]

Definition at line 44 of file compile_vect.hh.

00045         : ScalarCompiler(name,super,numInputs,numOutputs)
00046         {}

VectorCompiler::VectorCompiler ( Klass k  )  [inline]

Definition at line 48 of file compile_vect.hh.

00048                               : ScalarCompiler(k)
00049     {}


Member Function Documentation

void VectorCompiler::compileMultiSignal ( Tree  L  )  [virtual]

Reimplemented from ScalarCompiler.

Reimplemented in SchedulerCompiler.

Definition at line 30 of file compile_vect.cpp.

References Klass::addExecCode(), Klass::addSharedDecl(), Klass::addZone3(), Klass::closeLoop(), CS(), Compiler::fClass, Compiler::fDescription, Compiler::fUIRoot, Compiler::generateMacroInterfaceTree(), Compiler::generateUserInterfaceTree(), hd(), Klass::inputs(), isList(), Klass::openLoop(), Klass::outputs(), ScalarCompiler::prepare(), Compiler::prepareUserInterfaceTree(), subst(), T(), tl(), Description::ui(), xcast(), and xfloat().

00031 {
00032     //contextor recursivness(0);
00033     L = prepare(L);     // optimize, share and annotate expression
00034     
00035     for (int i = 0; i < fClass->inputs(); i++) {
00036         fClass->addZone3(subst("$1* input$0 = &input[$0][index];", T(i), xfloat()));
00037     }
00038     for (int i = 0; i < fClass->outputs(); i++) {
00039         fClass->addZone3(subst("$1* output$0 = &output[$0][index];", T(i), xfloat()));
00040     }
00041                 
00042     fClass->addSharedDecl("fullcount"); 
00043     fClass->addSharedDecl("input"); 
00044     fClass->addSharedDecl("output"); 
00045     
00046     for (int i = 0; isList(L); L = tl(L), i++) {
00047         Tree sig = hd(L);
00048         fClass->openLoop("count");
00049         fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast()));
00050         fClass->closeLoop();
00051     }
00052     
00053     generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
00054     generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
00055     if (fDescription) {
00056         fDescription->ui(prepareUserInterfaceTree(fUIRoot));
00057     }
00058 }

Here is the call graph for this function:

string VectorCompiler::CS ( Tree  sig  )  [protected, virtual]

Compile a signal.

Parameters:
sig the signal expression to compile.
Returns:
the C code translation of sig as a string

Reimplemented from ScalarCompiler.

Definition at line 66 of file compile_vect.cpp.

References Loop::addRecDependency(), Loop::fBackwardLoopDependencies, Compiler::fClass, Loop::findRecDefinition(), generateCode(), ScalarCompiler::getCompiledExpression(), Klass::getLoopProperty(), isProj(), isSigFixDelay(), ScalarCompiler::setCompiledExpression(), tl(), and Klass::topLoop().

Referenced by compileMultiSignal(), SchedulerCompiler::compileMultiSignal(), and generateFixDelay().

00067 {
00068     int         i;
00069     Tree        x;
00070     string      code;
00071     //cerr << "ENTER CS : "<< ppsig(sig) << endl;
00072     if (!getCompiledExpression(sig, code)) {
00073         code = generateCode(sig);
00074         //cerr << "CS : " << code << " for " << ppsig(sig) << endl;
00075         setCompiledExpression(sig, code);
00076     } else {
00077         // check for recursive dependencies
00078         Loop*   ls;
00079         Loop*   tl = fClass->topLoop();
00080         if (isProj(sig, &i, x) && tl->findRecDefinition(x)) {
00081             tl->addRecDependency(x);
00082             //cerr << "in CS : add rec dependency : " << tl << " --symbol--> " << x << endl;
00083         } else if (fClass->getLoopProperty(sig,ls)) {
00084             //cerr << "in CS : fBackwardLoopDependencies.insert : " << tl << " --depend(A)son--> " << ls << endl;
00085             tl->fBackwardLoopDependencies.insert(ls);
00086         } else {
00087             Tree    x,d;
00088             if (isSigFixDelay(sig, x, d)) {
00089                 if (fClass->getLoopProperty(x,ls)) {
00090                     //cerr << "in CS : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl;
00091                     tl->fBackwardLoopDependencies.insert(ls);
00092                 } else {
00093                     //cerr << "IMPOSSIBLE (dans l'etat des connaissances)" << endl;
00094                     //exit(1);
00095                 }
00096             } else {
00097                 //cerr << "in CS :  no loop property for : " << ppsig(sig) << endl;
00098             }
00099         }
00100     }
00101     //cerr << "EXIT CS : "<< ppsig(sig) << "---code---> " << code << endl;
00102     return code;
00103 }

Here is the call graph for this function:

Here is the caller graph for this function:

void VectorCompiler::dlineLoop ( const string &  tname,
const string &  dlname,
int  delay,
const string &  cexp 
) [protected, virtual]

Generate the code for a (short) delay line.

Parameters:
k the c++ class where the delay line will be placed.
l the loop where the code will be placed.
tname the name of the C++ type (float or int)
dlname the name of the delay line (vector) to be used.
delay the maximum delay
cexp the content of the signal as a C++ expression

Reimplemented in SchedulerCompiler.

Definition at line 392 of file compile_vect.cpp.

References Klass::addDeclCode(), Klass::addExecCode(), Klass::addFirstPrivateDecl(), Klass::addInitCode(), Klass::addPostCode(), Klass::addPreCode(), Klass::addSharedDecl(), Klass::addZone1(), Klass::addZone2(), Compiler::fClass, gMaxCopyDelay, gVecSize, ScalarCompiler::pow2limit(), subst(), and T().

Referenced by generateDelayLine().

00393 {
00394     if (delay < gMaxCopyDelay) {
00395         
00396         // Implementation of a copy based delayline
00397         
00398         // create names for temporary and permanent storage  
00399         string  buf = subst("$0_tmp", dlname);          
00400         string  pmem= subst("$0_perm", dlname);
00401         
00402         // constraints delay size to be multiple of 4
00403         delay = (delay+3)&-4;
00404         
00405         // allocate permanent storage for delayed samples
00406         string  dsize   = T(delay);
00407         fClass->addDeclCode(subst("$0 \t$1[$2];", tname, pmem, dsize));
00408         
00409         // init permanent memory
00410         fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", pmem, dsize)); 
00411         
00412         // compute method
00413         
00414         // -- declare a buffer and a "shifted" vector
00415         fClass->addSharedDecl(buf);
00416         
00417         // -- variables moved as class fields...
00418         fClass->addZone1(subst("$0 \t$1[$2+$3];", tname, buf, T(gVecSize), dsize));
00419         
00420         fClass->addFirstPrivateDecl(dlname);
00421         fClass->addZone2(subst("$0* \t$1 = &$2[$3];", tname, dlname, buf, dsize));
00422         
00423         // -- copy the stored samples to the delay line
00424         fClass->addPreCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[i];", buf, pmem, dsize));
00425         
00426         // -- compute the new samples
00427         fClass->addExecCode(subst("$0[i] = $1;", dlname, cexp));
00428         
00429         // -- copy back to stored samples
00430         fClass->addPostCode(subst("for (int i=0; i<$2; i++) $0[i]=$1[count+i];", pmem, buf, dsize));
00431         
00432     } else {
00433         
00434         // Implementation of a ring-buffer delayline
00435         
00436         // the size should be large enough and aligned on a power of two
00437         delay   = pow2limit(delay + gVecSize);
00438         string  dsize   = T(delay);
00439         string  mask    = T(delay-1);
00440         
00441         // create names for temporary and permanent storage  
00442         string  idx = subst("$0_idx", dlname);
00443         string  idx_save = subst("$0_idx_save", dlname);
00444         
00445         // allocate permanent storage for delayed samples
00446         fClass->addDeclCode(subst("$0 \t$1[$2];", tname, dlname, dsize));
00447         fClass->addDeclCode(subst("int \t$0;", idx));
00448         fClass->addDeclCode(subst("int \t$0;", idx_save));
00449         
00450         // init permanent memory
00451         fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i]=0;", dlname, dsize)); 
00452         fClass->addInitCode(subst("$0 = 0;", idx));
00453         fClass->addInitCode(subst("$0 = 0;", idx_save));
00454         
00455         // -- update index
00456         fClass->addPreCode(subst("$0 = ($0+$1)&$2;", idx, idx_save, mask));
00457         
00458         // -- compute the new samples
00459         fClass->addExecCode(subst("$0[($2+i)&$3] = $1;", dlname, cexp, idx, mask));
00460         
00461         // -- save index
00462         fClass->addPostCode(subst("$0 = count;", idx_save));
00463     }
00464 }

Here is the call graph for this function:

Here is the caller graph for this function:

string VectorCompiler::generateCacheCode ( Tree  sig,
const string &  exp 
) [protected, virtual]

Generate cache code for a signal if needed.

Parameters:
sig the signal expression.
exp the corresponding C code.
Returns:
the cached C code

Reimplemented from ScalarCompiler.

Definition at line 152 of file compile_vect.cpp.

References ScalarCompiler::fOccMarkup, generateDelayLine(), generateVariableStore(), Occurences::getMaxDelay(), ScalarCompiler::getSharingCount(), getSigType(), ScalarCompiler::getTypedNames(), kSamp, OccMarkup::retrieve(), ScalarCompiler::setVectorNameProperty(), subst(), and verySimple().

00153 {
00154     string      vname, ctype;
00155     int         sharing = getSharingCount(sig);
00156     Type        t = getSigType(sig);
00157     Occurences* o = fOccMarkup.retrieve(sig);
00158     int         d = o->getMaxDelay();
00159 
00160     if (t->variability() < kSamp) {
00161         if (d==0) {
00162             // non-sample, not delayed : same as scalar cache
00163             return ScalarCompiler::generateCacheCode(sig,exp);
00164 
00165         } else {
00166             // it is a non-sample expressions but used delayed
00167             // we need a delay line
00168             getTypedNames(getSigType(sig), "Vec", ctype, vname);
00169             if ((sharing > 1) && !verySimple(sig)) {
00170                 // first cache this expression because it
00171                 // it is shared and complex
00172                 string cachedexp =  generateVariableStore(sig, exp);
00173                 generateDelayLine(ctype, vname, d, cachedexp);
00174                 setVectorNameProperty(sig, vname);
00175                 return cachedexp;
00176             } else {
00177                 // no need to cache this expression because
00178                 // it is either not shared or very simple
00179                 generateDelayLine(ctype, vname, d, exp);
00180                 setVectorNameProperty(sig, vname);
00181                 return exp;
00182             }
00183         }
00184     } else {
00185         // sample-rate signal
00186         if (d > 0) {
00187             // used delayed : we need a delay line
00188             getTypedNames(getSigType(sig), "Yec", ctype, vname);
00189             generateDelayLine(ctype, vname, d, exp);
00190             setVectorNameProperty(sig, vname);
00191 
00192             if (verySimple(sig)) {
00193                 return exp;
00194             } else {
00195                 return subst("$0[i]", vname);
00196             }
00197         } else {
00198             // not delayed
00199             if ( sharing > 1 && ! verySimple(sig) ) {
00200                 // shared and not simple : we need a vector
00201                 // cerr << "ZEC : " << ppsig(sig) << endl;
00202                 getTypedNames(getSigType(sig), "Zec", ctype, vname);
00203                 generateDelayLine(ctype, vname, d, exp);
00204                 setVectorNameProperty(sig, vname);
00205                 return subst("$0[i]", vname);
00206            } else {
00207                 // not shared or simple : no cache needed
00208                 return exp;
00209             }
00210         }
00211     }
00212 }

Here is the call graph for this function:

string VectorCompiler::generateCode ( Tree  sig  )  [protected, virtual]

Compile a signal.

Parameters:
sig the signal expression to compile.
Returns:
the C code translation of sig as a string

Reimplemented from ScalarCompiler.

Definition at line 110 of file compile_vect.cpp.

References Loop::addRecDependency(), Klass::closeLoop(), Compiler::fClass, Loop::findRecDefinition(), isProj(), needSeparateLoop(), Klass::openLoop(), and Klass::topLoop().

Referenced by CS().

00111 {
00112     int     i;
00113     Tree    x;
00114     Loop*   l;
00115 
00116     l = fClass->topLoop();
00117     assert(l);
00118 
00119     if (needSeparateLoop(sig)) {
00120         // we need a separate loop unless it's an old recursion
00121         if (isProj(sig, &i, x)) {
00122             // projection of a recursive group x
00123             if (l->findRecDefinition(x)) {
00124                 // x is already in the loop stack
00125                 l->addRecDependency(x);
00126                 return ScalarCompiler::generateCode(sig);
00127             } else {
00128                 // x must be defined
00129                 fClass->openLoop(x, "count");
00130                 string c = ScalarCompiler::generateCode(sig);
00131                 fClass->closeLoop(sig);
00132                 return c;
00133             }
00134         } else {
00135             fClass->openLoop("count");
00136             string c = ScalarCompiler::generateCode(sig);
00137             fClass->closeLoop(sig);
00138             return c;
00139         }
00140     } else {
00141         return ScalarCompiler::generateCode(sig);
00142     }
00143 }

Here is the call graph for this function:

Here is the caller graph for this function:

void VectorCompiler::generateDelayLine ( const string &  ctype,
const string &  vname,
int  mxd,
const string &  exp 
) [protected, virtual]

Generate code for the delay mecchanism without using temporary variables.

Reimplemented from ScalarCompiler.

Definition at line 256 of file compile_vect.cpp.

References dlineLoop(), and vectorLoop().

Referenced by generateCacheCode(), and generateDelayVec().

00257 {
00258     if (mxd == 0) {
00259         vectorLoop(ctype, vname, exp);
00260     } else {
00261         dlineLoop(ctype, vname, mxd, exp);
00262     }
00263 }

Here is the call graph for this function:

Here is the caller graph for this function:

string VectorCompiler::generateDelayVec ( Tree  sig,
const string &  exp,
const string &  ctype,
const string &  vname,
int  mxd 
) [protected, virtual]

Generate code for the delay mecchanism.

The generated code depend of the maximum delay attached to exp and the "less temporaries" switch

Reimplemented from ScalarCompiler.

Definition at line 339 of file compile_vect.cpp.

References generateDelayLine(), ScalarCompiler::setVectorNameProperty(), subst(), and verySimple().

00340 {
00341     // it is a non-sample but used delayed
00342     // we need a delay line
00343     generateDelayLine(ctype, vname, mxd, exp);
00344     setVectorNameProperty(sig, vname);
00345     if (verySimple(sig)) {
00346         return exp;
00347     } else {
00348         return subst("$0[i]", vname);
00349     }
00350 }

Here is the call graph for this function:

string VectorCompiler::generateFixDelay ( Tree  sig,
Tree  exp,
Tree  delay 
) [protected, virtual]

Generate code for accessing a delayed signal.

The generated code depend of the maximum delay attached to exp and the gLessTempSwitch.

Reimplemented from ScalarCompiler.

Definition at line 285 of file compile_vect.cpp.

References CS(), ScalarCompiler::fOccMarkup, Occurences::getMaxDelay(), ScalarCompiler::getVectorNameProperty(), gMaxCopyDelay, gVecSize, isSigInt(), ScalarCompiler::pow2limit(), OccMarkup::retrieve(), subst(), and T().

00286 {
00287     int     mxd, d; 
00288     string  vecname;
00289  
00290     //cerr << "VectorCompiler::generateFixDelay " << ppsig(sig) << endl;
00291 
00292     CS(exp); // ensure exp is compiled to have a vector name
00293 
00294     mxd = fOccMarkup.retrieve(exp)->getMaxDelay();
00295 
00296     if (! getVectorNameProperty(exp, vecname)) {
00297         cerr << "no vector name for " << ppsig(exp) << endl;
00298         exit(1);
00299     }
00300 
00301     if (mxd == 0) {
00302         // not a real vector name but a scalar name
00303         return subst("$0[i]", vecname);
00304 
00305     } else if (mxd < gMaxCopyDelay){
00306         if (isSigInt(delay, &d)) {
00307             if (d == 0) {
00308                 return subst("$0[i]", vecname);
00309             } else {
00310                 return subst("$0[i-$1]", vecname, T(d));
00311             }
00312         } else {
00313             return subst("$0[i-$1]", vecname, CS(delay));
00314         }
00315 
00316     } else {
00317 
00318         // long delay : we use a ring buffer of size 2^x
00319         int     N   = pow2limit( mxd+gVecSize );
00320 
00321         if (isSigInt(delay, &d)) {
00322             if (d == 0) {
00323                 return subst("$0[($0_idx+i)&$1]", vecname, T(N-1));
00324             } else {
00325                 return subst("$0[($0_idx+i-$2)&$1]", vecname, T(N-1), T(d));
00326             }
00327         } else {
00328             return subst("$0[($0_idx+i-$2)&$1]", vecname, T(N-1), CS(delay));
00329         }
00330     }
00331 }

Here is the call graph for this function:

string VectorCompiler::generateVariableStore ( Tree  sig,
const string &  exp 
) [protected, virtual]

Reimplemented from ScalarCompiler.

Definition at line 265 of file compile_vect.cpp.

References getSigType(), ScalarCompiler::getTypedNames(), kSamp, subst(), and vectorLoop().

Referenced by generateCacheCode().

00266 {
00267     Type        t = getSigType(sig);
00268 
00269     if (getSigType(sig)->variability() == kSamp) {
00270         string      vname, ctype;
00271         getTypedNames(t, "Vector", ctype, vname);
00272         vectorLoop(ctype, vname, exp);
00273         return subst("$0[i]", vname);
00274     } else {
00275         return ScalarCompiler::generateVariableStore(sig, exp);
00276     }
00277 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool VectorCompiler::needSeparateLoop ( Tree  sig  )  [protected]

Test if a signal need to be compiled in a separate loop.

Parameters:
sig the signal expression to test.
Returns:
true if a separate loop is needed

Definition at line 219 of file compile_vect.cpp.

References ScalarCompiler::fOccMarkup, Occurences::getMaxDelay(), ScalarCompiler::getSharingCount(), getSigType(), isProj(), isSigFixDelay(), kSamp, OccMarkup::retrieve(), and verySimple().

Referenced by generateCode().

00220 {
00221     Occurences* o = fOccMarkup.retrieve(sig);
00222     Type        t = getSigType(sig);
00223     int         c = getSharingCount(sig);
00224     bool        b;
00225 
00226     int         i;
00227     Tree        x,y;
00228 
00229 
00230     if (o->getMaxDelay()>0) {
00231         //cerr << "DLY "; // delayed expressions require a separate loop
00232         b = true;
00233     } else if (verySimple(sig) || t->variability()<kSamp) {
00234         b = false;      // non sample computation never require a loop
00235     } else if (isSigFixDelay(sig, x, y)) {
00236         b = false;      // 
00237     } else if (isProj(sig, &i ,x)) {
00238         //cerr << "REC "; // recursive expressions require a separate loop
00239         b = true;
00240     } else if (c > 1) {
00241         //cerr << "SHA(" << c << ") "; // expressions used several times required a separate loop
00242         b = true;
00243     } else {
00244         // sample expressions that are not recursive, not delayed
00245         // and not shared, doesn't require a separate loop.
00246         b = false;
00247     }
00248 /*    if (b) {
00249         cerr << "Separate Loop for " << ppsig(sig) << endl;
00250     } else {
00251         cerr << "Same Loop for " << ppsig(sig) << endl;
00252     }*/
00253     return b;
00254 }

Here is the call graph for this function:

Here is the caller graph for this function:

void VectorCompiler::vectorLoop ( const string &  tname,
const string &  vecname,
const string &  cexp 
) [protected, virtual]

Generate the code for a (short) delay line.

Parameters:
k the c++ class where the delay line will be placed.
l the loop where the code will be placed.
tname the name of the C++ type (float or int)
dlname the name of the delay line (vector) to be used.
delay the maximum delay
cexp the content of the signal as a C++ expression

Reimplemented in SchedulerCompiler.

Definition at line 370 of file compile_vect.cpp.

References Klass::addExecCode(), Klass::addSharedDecl(), Klass::addZone1(), Compiler::fClass, gVecSize, subst(), and T().

Referenced by generateDelayLine(), and generateVariableStore().

00371 {  
00372     // -- declare the vector
00373     fClass->addSharedDecl(vecname);
00374     
00375     // -- variables moved as class fields...
00376     fClass->addZone1(subst("$0 \t$1[$2];", tname, vecname, T(gVecSize)));
00377     
00378     // -- compute the new samples
00379     fClass->addExecCode(subst("$0[i] = $1;", vecname, cexp));
00380 }

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this class was generated from the following files:
Generated on Thu Jul 15 15:47:37 2010 for FAUST compiler by  doxygen 1.6.3