VectorCompiler Class Reference

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

#include <compile_vect.hh>

Inherits ScalarCompiler.

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.
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.

Definition at line 32 of file compile_vect.cpp.

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

00033 {
00034     //contextor recursivness(0);
00035     L = prepare(L);     // optimize, share and annotate expression
00036     
00037     for (int i = 0; i < fClass->inputs(); i++) {
00038         if (gSchedulerSwitch) {
00039             fClass->addZone3(subst("$1* input$0 = &input[$0][fIndex];", T(i), xfloat()));
00040         } else {
00041             fClass->addZone3(subst("$1* input$0 = &input[$0][index];", T(i), xfloat()));
00042         }
00043     }
00044     for (int i = 0; i < fClass->outputs(); i++) {
00045         if (gSchedulerSwitch) {
00046             fClass->addZone3(subst("$1* output$0 = &output[$0][fIndex];", T(i), xfloat()));
00047         } else {
00048             fClass->addZone3(subst("$1* output$0 = &output[$0][index];", T(i), xfloat()));
00049         }
00050     }
00051                 
00052     fClass->addSharedDecl("fullcount"); 
00053     fClass->addSharedDecl("input"); 
00054     fClass->addSharedDecl("output"); 
00055     
00056     for (int i = 0; isList(L); L = tl(L), i++) {
00057         Tree sig = hd(L);
00058         fClass->openLoop("count");
00059         fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast()));
00060         fClass->closeLoop();
00061     }
00062     
00063     if (gSchedulerSwitch) {
00064         // Build tasks list 
00065         fClass->buildTasksList();
00066     }
00067     
00068     generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
00069     generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
00070     if (fDescription) {
00071         fDescription->ui(prepareUserInterfaceTree(fUIRoot));
00072     }
00073 }

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 81 of file compile_vect.cpp.

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

Referenced by compileMultiSignal(), and generateFixDelay().

00082 {
00083     int         i;
00084     Tree        x;
00085     string      code;
00086 
00087     if (!getCompiledExpression(sig, code)) {
00088         code = generateCode(sig);
00089         //cerr << "CS : " << code << " for " << ppsig(sig) << endl;
00090         setCompiledExpression(sig, code);
00091     } else {
00092         // check for recursive dependencies
00093         Loop*   ls;
00094         Loop*   tl = fClass->topLoop();
00095         if (isProj(sig, &i, x) && tl->findRecDefinition(x)) {
00096             tl->addRecDependency(x);
00097         } else if (fClass->getLoopProperty(sig,ls)) {
00098             //cerr << "in CS : fBackwardLoopDependencies.insert : " << tl << " --dependson--> " << ls << endl;
00099             tl->fBackwardLoopDependencies.insert(ls);
00100         } else {
00101            //cerr << "in CS :  no loop property for : " << ppsig(sig) << endl;
00102 
00103         }
00104     }
00105     return code;
00106 }

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 155 of file compile_vect.cpp.

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

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

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 113 of file compile_vect.cpp.

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

Referenced by CS().

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

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 258 of file compile_vect.cpp.

References dlineLoop(), Compiler::fClass, and vectorLoop().

Referenced by generateCacheCode(), and generateDelayVec().

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

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 342 of file compile_vect.cpp.

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

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

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 288 of file compile_vect.cpp.

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

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

Here is the call graph for this function:

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

Reimplemented from ScalarCompiler.

Definition at line 268 of file compile_vect.cpp.

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

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

Here is the call 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 218 of file compile_vect.cpp.

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

Referenced by generateCode().

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

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 Apr 29 00:00:24 2010 for FAUST compiler by  doxygen 1.6.3