Compile a list of FAUST signals into a vector C++ class. More...
#include <compile_vect.hh>
Inherits ScalarCompiler.
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. |
Compile a list of FAUST signals into a vector C++ class.
Definition at line 39 of file compile_vect.hh.
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 {}
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 }
string VectorCompiler::CS | ( | Tree | sig | ) | [protected, virtual] |
Compile a signal.
sig | the signal expression to compile. |
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 }
string VectorCompiler::generateCacheCode | ( | Tree | sig, | |
const string & | exp | |||
) | [protected, virtual] |
Generate cache code for a signal if needed.
sig | the signal expression. | |
exp | the corresponding 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 }
string VectorCompiler::generateCode | ( | Tree | sig | ) | [protected, virtual] |
Compile a signal.
sig | the signal expression to compile. |
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 }
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 }
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 }
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 }
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 }
bool VectorCompiler::needSeparateLoop | ( | Tree | sig | ) | [protected] |
Test if a signal need to be compiled in a separate loop.
sig | the signal expression to test. |
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 }