|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 00022 00023 00024 /********************************************************************** 00025 - klass.cpp : class C++ a remplir (projet FAUST) - 00026 00027 00028 Historique : 00029 ----------- 00030 17-10-2001 : implementation initiale (yo) 00031 18-10-2001 : Ajout de getFreshID (yo) 00032 02-11-2001 : Ajout de sous classes (yo) 00033 06-11-2001 : modif impression des classes (yo) 00034 00035 ***********************************************************************/ 00036 00037 #include <stdio.h> 00038 #include <iostream> 00039 #include <sstream> 00040 #include <string> 00041 #include <list> 00042 #include <map> 00043 00044 #include "floats.hh" 00045 #include "smartpointer.hh" 00046 #include "klass.hh" 00047 #include "uitree.hh" 00048 #include "Text.hh" 00049 #include "signals.hh" 00050 #include "ppsig.hh" 00051 #include "recursivness.hh" 00052 00053 00054 extern bool gVectorSwitch; 00055 extern bool gDeepFirstSwitch; 00056 extern bool gOpenMPSwitch; 00057 extern bool gOpenMPLoop; 00058 extern bool gSchedulerSwitch; 00059 extern int gVecSize; 00060 extern bool gUIMacroSwitch; 00061 extern int gVectorLoopVariant; 00062 extern bool gGroupTaskSwitch; 00063 00064 extern map<Tree, set<Tree> > gMetaDataSet; 00065 static int gTaskCount = 0; 00066 00067 void tab (int n, ostream& fout) 00068 { 00069 fout << '\n'; 00070 while (n--) fout << '\t'; 00071 } 00072 00073 bool Klass::fNeedPowerDef = false; 00074 00078 void Klass::setLoopProperty(Tree sig, Loop* l) 00079 { 00080 fLoopProperty.set(sig,l); 00081 } 00082 00086 bool Klass::getLoopProperty(Tree sig, Loop*& l) 00087 { 00088 return fLoopProperty.get(sig, l); 00089 } 00090 00095 void Klass::openLoop(const string& size) 00096 { 00097 fTopLoop = new Loop(fTopLoop, size); 00098 //cerr << "\nOPEN SHARED LOOP(" << size << ") ----> " << fTopLoop << endl; 00099 } 00100 00106 void Klass::openLoop(Tree recsymbol, const string& size) 00107 { 00108 fTopLoop = new Loop(recsymbol, fTopLoop, size); 00109 //cerr << "\nOPEN REC LOOP(" << *recsymbol << ", " << size << ") ----> " << fTopLoop << endl; 00110 } 00111 00116 void Klass::closeLoop(Tree sig) 00117 { 00118 assert(fTopLoop); 00119 Loop* l = fTopLoop; 00120 fTopLoop = l->fEnclosingLoop; 00121 assert(fTopLoop); 00122 00123 //l->println(4, cerr); 00124 //cerr << endl; 00125 00126 Tree S = symlist(sig); 00127 //cerr << "CLOSE LOOP :" << l << " with symbols " << *S << endl; 00128 if (l->isEmpty() || fTopLoop->hasRecDependencyIn(S)) { 00129 //cout << " will absorb" << endl; 00130 // empty or dependent loop -> absorbed by enclosing one 00131 //cerr << "absorbed by : " << fTopLoop << endl; 00132 fTopLoop->absorb(l); 00133 //delete l; HACK !!! 00134 } else { 00135 // cout << " will NOT absorb" << endl; 00136 // we have an independent loop 00137 setLoopProperty(sig,l); // associate the signal 00138 fTopLoop->fBackwardLoopDependencies.insert(l); 00139 // we need to indicate that all recursive symbols defined 00140 // in this loop are defined in this loop 00141 for (Tree lsym=l->fRecSymbolSet; !isNil(lsym); lsym=tl(lsym)) { 00142 this->setLoopProperty(hd(lsym), l); 00143 //cerr << "loop " << l << " defines " << *hd(lsym) << endl; 00144 } 00145 } 00146 //cerr << "\n" << endl; 00147 } 00148 00152 void printlines(int n, list<string>& lines, ostream& fout) 00153 { 00154 list<string>::iterator s; 00155 for (s = lines.begin(); s != lines.end(); s++) { 00156 tab(n, fout); fout << *s; 00157 } 00158 } 00159 00163 void printdecllist(int n, const string& decl, list<string>& content, ostream& fout) 00164 { 00165 if (!content.empty()) { 00166 list<string>::iterator s; 00167 fout << "\\"; 00168 tab(n, fout); fout << decl; 00169 string sep = "("; 00170 for (s = content.begin(); s != content.end(); s++) { 00171 fout << sep << *s; 00172 sep = ", "; 00173 } 00174 fout << ')'; 00175 } 00176 } 00177 00181 void Klass::printLibrary(ostream& fout) 00182 { 00183 set<string> S; 00184 set<string>::iterator f; 00185 00186 string sep; 00187 collectLibrary(S); 00188 fout << "/* link with "; 00189 for (f = S.begin(), sep =": "; f != S.end(); f++, sep = ", ") { 00190 fout << sep << *f; 00191 } 00192 fout << " */\n"; 00193 } 00194 00198 void Klass::printIncludeFile(ostream& fout) 00199 { 00200 set<string> S; 00201 set<string>::iterator f; 00202 00203 if (gOpenMPSwitch) { 00204 fout << "#include <omp.h>" << "\n"; 00205 } 00206 00207 collectIncludeFile(S); 00208 for (f = S.begin(); f != S.end(); f++) { 00209 fout << "#include " << *f << "\n"; 00210 } 00211 } 00212 00216 void Klass::printAdditionalCode(ostream& fout) 00217 { 00218 if (fNeedPowerDef) { 00219 // Add faustpower definition to C++ code 00220 fout << "#include <cmath>" << endl; 00221 fout << "template <int N> inline float faustpower(float x) { return powf(x,N); } " << endl; 00222 fout << "template <int N> inline double faustpower(double x) { return pow(x,N); }" << endl; 00223 fout << "template <int N> inline int faustpower(int x) { return faustpower<N/2>(x) * faustpower<N-N/2>(x); } " << endl; 00224 fout << "template <> inline int faustpower<0>(int x) { return 1; }" << endl; 00225 fout << "template <> inline int faustpower<1>(int x) { return x; }" << endl; 00226 } 00227 00228 } 00229 00233 void Klass::printMetadata(int n, const map<Tree, set<Tree> >& S, ostream& fout) 00234 { 00235 tab(n,fout); fout << "static void metadata(Meta* m) \t{ "; 00236 00237 for (map<Tree, set<Tree> >::iterator i = gMetaDataSet.begin(); i != gMetaDataSet.end(); i++) { 00238 if (i->first != tree("author")) { 00239 tab(n+1,fout); fout << "m->declare(\"" << *(i->first) << "\", " << **(i->second.begin()) << ");"; 00240 } else { 00241 for (set<Tree>::iterator j = i->second.begin(); j != i->second.end(); j++) { 00242 if (j == i->second.begin()) { 00243 tab(n+1,fout); fout << "m->declare(\"" << *(i->first) << "\", " << **j << ");" ; 00244 } else { 00245 tab(n+1,fout); fout << "m->declare(\"" << "contributor" << "\", " << **j << ");"; 00246 } 00247 } 00248 } 00249 } 00250 00251 tab(n,fout); fout << "}" << endl; 00252 } 00253 00254 inline bool isElement(const set<Loop*>& S, Loop* l) 00255 { 00256 return S.find(l)!= S.end(); 00257 } 00258 00262 void Klass::printLoopDeepFirst(int n, ostream& fout, Loop* l, set<Loop*>& visited) 00263 { 00264 // avoid printing already printed loops 00265 if (isElement(visited, l)) return; 00266 00267 // remember we have printed this loop 00268 visited.insert(l); 00269 00270 // print the dependencies loops (that need to be computed before this one) 00271 for (lset::const_iterator p =l->fBackwardLoopDependencies.begin(); p!=l->fBackwardLoopDependencies.end(); p++) { 00272 printLoopDeepFirst(n, fout, *p, visited); 00273 } 00274 // the print the loop itself 00275 tab(n, fout); 00276 tab(n, fout); fout << "// LOOP " << l << ", ORDER " << l->fOrder << endl; 00277 l->println(n+1, fout); 00278 } 00279 00283 static void computeUseCount(Loop* l) 00284 { 00285 l->fUseCount++; 00286 if (l->fUseCount == 1) { 00287 for (lset::iterator p =l->fBackwardLoopDependencies.begin(); p!=l->fBackwardLoopDependencies.end(); p++) { 00288 computeUseCount(*p); 00289 } 00290 } 00291 } 00292 00296 static void groupSeqLoops(Loop* l) 00297 { 00298 int n = l->fBackwardLoopDependencies.size(); 00299 if (n==0) { 00300 return; 00301 } else if (n==1) { 00302 Loop* f = *(l->fBackwardLoopDependencies.begin()); 00303 if (f->fUseCount == 1) { 00304 l->concat(f); 00305 groupSeqLoops(l); 00306 } else { 00307 groupSeqLoops(f); 00308 } 00309 return; 00310 } else if (n > 1) { 00311 for (lset::iterator p =l->fBackwardLoopDependencies.begin(); p!=l->fBackwardLoopDependencies.end(); p++) { 00312 groupSeqLoops(*p); 00313 } 00314 } 00315 } 00316 00317 #define WORK_STEALING_INDEX 0 00318 #define LAST_TASK_INDEX 1 00319 #define START_TASK_INDEX LAST_TASK_INDEX + 1 00320 00321 #define START_TASK_MAX 2 00322 00323 void Klass::buildTasksList() 00324 { 00325 lgraph G; 00326 00327 if (gGroupTaskSwitch) { 00328 computeUseCount(fTopLoop); 00329 groupSeqLoops(fTopLoop); 00330 } 00331 00332 sortGraph(fTopLoop, G); 00333 int index_task = START_TASK_INDEX; 00334 00335 addDeclCode("TaskGraph fGraph;"); 00336 addDeclCode("FAUSTFLOAT** input;"); 00337 addDeclCode("FAUSTFLOAT** output;"); 00338 addDeclCode("volatile bool fIsFinished;"); 00339 addDeclCode("int fFullCount;"); 00340 addDeclCode("int fIndex;"); 00341 addDeclCode("DSPThreadPool* fThreadPool;"); 00342 addDeclCode("int fStaticNumThreads;"); 00343 addDeclCode("int fDynamicNumThreads;"); 00344 00345 // Compute forward dependencies 00346 for (int l=G.size()-1; l>=0; l--) { 00347 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00348 for (lset::const_iterator p1 = (*p)->fBackwardLoopDependencies.begin(); p1!=(*p)->fBackwardLoopDependencies.end(); p1++) { 00349 (*p1)->fForwardLoopDependencies.insert((*p)); 00350 } 00351 (*p)->fIndex = index_task; 00352 index_task++; 00353 } 00354 } 00355 00356 // Compute ready tasks list 00357 vector<int> task_num; 00358 for (int l=G.size()-1; l>=0; l--) { 00359 lset::const_iterator next; 00360 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00361 if ((*p)->fBackwardLoopDependencies.size() == 0) { 00362 task_num.push_back((*p)->fIndex); 00363 } 00364 } 00365 } 00366 00367 if (task_num.size() < START_TASK_MAX) { 00368 00369 // Push ready tasks thread 0, execute one task directly 00370 00371 addZone3("if (cur_thread == 0) {"); 00372 00373 Loop* keep = NULL; 00374 for (int l=G.size()-1; l>=0; l--) { 00375 lset::const_iterator next; 00376 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00377 if ((*p)->fBackwardLoopDependencies.size() == 0) { 00378 if (keep == NULL) { 00379 keep = *p; 00380 } else { 00381 addZone3(subst(" taskqueue.PushHead($0);", T((*p)->fIndex))); 00382 } 00383 } 00384 } 00385 } 00386 00387 if (keep != NULL) { 00388 addZone3(subst(" tasknum = $0;", T(keep->fIndex))); 00389 } 00390 00391 addZone3("} else {"); 00392 addZone3(" tasknum = TaskQueue::GetNextTask(cur_thread, fDynamicNumThreads);"); 00393 addZone3("}"); 00394 00395 } else { 00396 00397 // Cut ready tasks list and have each thread (dynamically) use a subpart 00398 addZone3(subst("int task_list_size = $0;", T((int)task_num.size()))); 00399 stringstream buf; 00400 buf << "int task_list[" << task_num.size() << "] = {"; 00401 for(size_t i = 0; i < task_num.size(); i++) { 00402 buf << task_num[i]; 00403 if (i != (task_num.size() - 1)) 00404 buf << ","; 00405 } 00406 buf << "};"; 00407 00408 addZone3(buf.str()); 00409 addZone3("taskqueue.InitTaskList(task_list_size, task_list, fDynamicNumThreads, cur_thread, tasknum);"); 00410 } 00411 00412 // Last stage connected to end task 00413 if (G[0].size() > 1) { 00414 addZone2c("// Initialize end task, if more than one input"); 00415 addZone2c(subst("fGraph.InitTask($0,$1);", T(LAST_TASK_INDEX), T((int)G[0].size()))); 00416 } else { 00417 addZone2c("// End task has only one input, so will be directly activated"); 00418 } 00419 00420 // Compute init section 00421 addZone2c("// Only initialize taks with more than one input"); 00422 for (int l=G.size()-1; l>=0; l--) { 00423 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00424 if ((*p)->fBackwardLoopDependencies.size() > 1) { // Only initialize taks with more than 1 input, since taks with one input are "directly" activated. 00425 addZone2c(subst("fGraph.InitTask($0,$1);", T(START_TASK_INDEX + gTaskCount++), T((int)(*p)->fBackwardLoopDependencies.size()))); 00426 } else { 00427 gTaskCount++; 00428 } 00429 } 00430 } 00431 00432 addInitCode("fStaticNumThreads = get_max_cpu();"); 00433 addInitCode("fDynamicNumThreads = getenv(\"OMP_NUM_THREADS\") ? atoi(getenv(\"OMP_NUM_THREADS\")) : fStaticNumThreads;"); 00434 addInitCode("fThreadPool = DSPThreadPool::Init();"); 00435 addInitCode("fThreadPool->StartAll(fStaticNumThreads - 1, false);"); 00436 00437 gTaskCount = 0; 00438 } 00439 00443 void Klass::printLoopGraphVector(int n, ostream& fout) 00444 { 00445 if (gGroupTaskSwitch) { 00446 computeUseCount(fTopLoop); 00447 groupSeqLoops(fTopLoop); 00448 } 00449 00450 lgraph G; 00451 sortGraph(fTopLoop, G); 00452 00453 #if 1 00454 // EXPERIMENTAL 00455 if (gVectorSwitch && gDeepFirstSwitch) { 00456 set<Loop*> visited; 00457 printLoopDeepFirst(n, fout, fTopLoop, visited); 00458 return; 00459 } 00460 #endif 00461 00462 // normal mode 00463 for (int l=G.size()-1; l>=0; l--) { 00464 if (gVectorSwitch) { tab(n, fout); fout << "// SECTION : " << G.size() - l; } 00465 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00466 (*p)->println(n, fout); 00467 } 00468 } 00469 } 00470 00474 void Klass::printLoopGraphOpenMP(int n, ostream& fout) 00475 { 00476 if (gGroupTaskSwitch) { 00477 computeUseCount(fTopLoop); 00478 groupSeqLoops(fTopLoop); 00479 } 00480 00481 lgraph G; 00482 sortGraph(fTopLoop, G); 00483 00484 // OpenMP mode : add OpenMP directives 00485 for (int l=G.size()-1; l>=0; l--) { 00486 tab(n, fout); fout << "// SECTION : " << G.size() - l; 00487 printLoopLevelOpenMP(n, G.size() - l, G[l], fout); 00488 } 00489 } 00490 00494 void Klass::printLoopGraphScheduler(int n, ostream& fout) 00495 { 00496 if (gGroupTaskSwitch) { 00497 computeUseCount(fTopLoop); 00498 groupSeqLoops(fTopLoop); 00499 } 00500 00501 lgraph G; 00502 sortGraph(fTopLoop, G); 00503 00504 // OpenMP mode : add OpenMP directives 00505 for (int l=G.size()-1; l>0; l--) { 00506 tab(n, fout); fout << "// SECTION : " << G.size() - l; 00507 printLoopLevelScheduler(n, G.size() - l, G[l], fout); 00508 } 00509 00510 printLastLoopLevelScheduler(n, G.size(), G[0], fout); 00511 } 00512 00513 00517 void Klass::printGraphDotFormat(ostream& fout) 00518 { 00519 lgraph G; 00520 sortGraph(fTopLoop, G); 00521 00522 fout << "strict digraph loopgraph {" << endl; 00523 fout << '\t' << "rankdir=LR;" << endl; 00524 fout << '\t' << "node[color=blue, fillcolor=lightblue, style=filled, fontsize=9];" << endl; 00525 00526 int lnum = 0; // used for loop numbers 00527 // for each level of the graph 00528 for (int l=G.size()-1; l>=0; l--) { 00529 // for each task in the level 00530 for (lset::const_iterator t =G[l].begin(); t!=G[l].end(); t++) { 00531 // print task label "Lxxx : 0xffffff" 00532 fout << '\t' << 'L'<<(*t)<<"[label=<<font face=\"verdana,bold\">L"<<lnum++<<"</font> : "<<(*t)<<">];"<<endl; 00533 // for each source of the task 00534 for (lset::const_iterator src = (*t)->fBackwardLoopDependencies.begin(); src!=(*t)->fBackwardLoopDependencies.end(); src++) { 00535 // print the connection Lxxx -> Lyyy; 00536 fout << '\t' << 'L'<<(*src)<<"->"<<'L'<<(*t)<<';'<<endl; 00537 } 00538 } 00539 } 00540 fout << "}" << endl; 00541 } 00542 00546 void Klass::printLoopGraphInternal(int n, ostream& fout) 00547 { 00548 lgraph G; 00549 sortGraph(fTopLoop, G); 00550 00551 // normal mode 00552 for (int l=G.size()-1; l>=0; l--) { 00553 if (gVectorSwitch) { tab(n, fout); fout << "// SECTION : " << G.size() - l; } 00554 for (lset::const_iterator p =G[l].begin(); p!=G[l].end(); p++) { 00555 (*p)->printoneln(n, fout); 00556 } 00557 } 00558 } 00559 00563 void Klass::printLoopGraphScalar(int n, ostream& fout) 00564 { 00565 fTopLoop->printoneln(n, fout); 00566 } 00567 00571 static bool nonRecursiveLevel(const lset& L) 00572 { 00573 for (lset::const_iterator p =L.begin(); p!=L.end(); p++) { 00574 if ((*p)->fIsRecursive) return false; 00575 } 00576 return true; 00577 } 00578 00583 void Klass::printLoopLevelOpenMP(int n, int lnum, const lset& L, ostream& fout) 00584 { 00585 if (nonRecursiveLevel(L) && L.size()==1) { 00586 for (lset::const_iterator p =L.begin(); p!=L.end(); p++) { 00587 if ((*p)->isEmpty() == false) { 00588 if (gOpenMPLoop) { 00589 (*p)->printParLoopln(n, fout); 00590 } else { 00591 tab(n, fout); fout << "#pragma omp single "; 00592 tab(n, fout); fout << "{ "; 00593 (*p)->println(n+1, fout); 00594 tab(n, fout); fout << "} "; 00595 } 00596 } 00597 } 00598 00599 } else if (L.size() > 1) { 00600 tab(n, fout); fout << "#pragma omp sections "; 00601 tab(n, fout); fout << "{ "; 00602 for (lset::const_iterator p =L.begin(); p!=L.end(); p++) { 00603 tab(n+1, fout); fout << "#pragma omp section "; 00604 tab(n+1, fout); fout << "{"; 00605 (*p)->println(n+2, fout); 00606 tab(n+1, fout); fout << "} "; 00607 } 00608 tab(n, fout); fout << "} "; 00609 } else if (L.size() == 1 && !(*L.begin())->isEmpty()) { 00610 tab(n, fout); fout << "#pragma omp single "; 00611 tab(n, fout); fout << "{ "; 00612 for (lset::const_iterator p =L.begin(); p!=L.end(); p++) { 00613 (*p)->println(n+1, fout); 00614 } 00615 tab(n, fout); fout << "} "; 00616 } 00617 } 00618 00623 void Klass::printLastLoopLevelScheduler(int n, int lnum, const lset& L, ostream& fout) 00624 { 00625 if (nonRecursiveLevel(L) && L.size() == 1 && !(*L.begin())->isEmpty()) { 00626 00627 lset::const_iterator p =L.begin(); 00628 tab(n, fout); fout << "case " << gTaskCount++ << ": { "; 00629 (*p)->println(n+1, fout); 00630 tab(n+1, fout); fout << "tasknum = LAST_TASK_INDEX;"; 00631 tab(n+1, fout); fout << "break;"; 00632 tab(n, fout); fout << "} "; 00633 00634 } else if (L.size() > 1) { 00635 00636 for (lset::const_iterator p =L.begin(); p!=L.end(); p++) { 00637 tab(n, fout); fout << "case " << gTaskCount++ << ": { "; 00638 (*p)->println(n+1, fout); 00639 tab(n+1, fout); fout << "fGraph.ActivateOneOutputTask(taskqueue, LAST_TASK_INDEX, tasknum);"; 00640 tab(n+1, fout); fout << "break;"; 00641 tab(n, fout); fout << "} "; 00642 } 00643 00644 } else if (L.size() == 1 && !(*L.begin())->isEmpty()) { 00645 00646 lset::const_iterator p =L.begin(); 00647 tab(n, fout); fout << "case " << gTaskCount++ << ": { "; 00648 (*p)->println(n+1, fout); 00649 tab(n+1, fout); fout << "tasknum = LAST_TASK_INDEX;"; 00650 tab(n+1, fout); fout << "break;"; 00651 tab(n, fout); fout << "} "; 00652 00653 } 00654 } 00655 00656 void Klass::printOneLoopScheduler(lset::const_iterator p, int n, ostream& fout) 00657 { 00658 tab(n, fout); fout << "case " << gTaskCount++ << ": { "; 00659 (*p)->println(n+1, fout); 00660 00661 // One output only 00662 if ((*p)->fForwardLoopDependencies.size() == 1) { 00663 00664 lset::const_iterator p1 = (*p)->fForwardLoopDependencies.begin(); 00665 if ((*p1)->fBackwardLoopDependencies.size () == 1) { 00666 tab(n+1, fout); fout << subst("tasknum = $0;", T((*p1)->fIndex)); 00667 } else { 00668 tab(n+1, fout); fout << subst("fGraph.ActivateOneOutputTask(taskqueue, $0, tasknum);", T((*p1)->fIndex)); 00669 } 00670 00671 } else { 00672 00673 Loop* keep = NULL; 00674 // Find one output with only one backward dependencies 00675 for (lset::const_iterator p1 = (*p)->fForwardLoopDependencies.begin(); p1!=(*p)->fForwardLoopDependencies.end(); p1++) { 00676 if ((*p1)->fBackwardLoopDependencies.size () == 1) { 00677 keep = *p1; 00678 break; 00679 } 00680 } 00681 00682 if (keep == NULL) { 00683 tab(n+1, fout); fout << "tasknum = WORK_STEALING_INDEX;"; 00684 } 00685 00686 for (lset::const_iterator p1 = (*p)->fForwardLoopDependencies.begin(); p1!=(*p)->fForwardLoopDependencies.end(); p1++) { 00687 if ((*p1)->fBackwardLoopDependencies.size () == 1) { // Task is the only input 00688 if (*p1 != keep) { 00689 tab(n+1, fout); fout << subst("taskqueue.PushHead($0);", T((*p1)->fIndex)); 00690 } 00691 } else { 00692 if (keep == NULL) { 00693 tab(n+1, fout); fout << subst("fGraph.ActivateOutputTask(taskqueue, $0, tasknum);", T((*p1)->fIndex)); 00694 } else { 00695 tab(n+1, fout); fout << subst("fGraph.ActivateOutputTask(taskqueue, $0);", T((*p1)->fIndex)); 00696 } 00697 } 00698 } 00699 00700 if (keep != NULL) { 00701 tab(n+1, fout); fout << subst("tasknum = $0;", T(keep->fIndex)); // Last one 00702 } else { 00703 tab(n+1, fout); fout << "fGraph.GetReadyTask(taskqueue, tasknum);"; // Last one 00704 } 00705 } 00706 00707 tab(n+1, fout); fout << "break;"; 00708 tab(n, fout); fout << "} "; 00709 } 00710 00716 void Klass::printLoopLevelScheduler(int n, int lnum, const lset& L, ostream& fout) 00717 { 00718 if (nonRecursiveLevel(L) && L.size() == 1 && !(*L.begin())->isEmpty()) { 00719 printOneLoopScheduler(L.begin(), n, fout); 00720 } else if (L.size() > 1) { 00721 for (lset::const_iterator p = L.begin(); p != L.end(); p++) { 00722 printOneLoopScheduler(p, n, fout); 00723 } 00724 } else if (L.size() == 1 && !(*L.begin())->isEmpty()) { 00725 printOneLoopScheduler(L.begin(), n, fout); 00726 } 00727 } 00728 00732 void Klass::println(int n, ostream& fout) 00733 { 00734 list<Klass* >::iterator k; 00735 00736 tab(n,fout); fout << "#define FAUSTCLASS "<< fKlassName << endl; 00737 00738 if (gSchedulerSwitch) { 00739 tab(n,fout); fout << "class " << fKlassName << " : public " << fSuperKlassName << ", public Runnable {"; 00740 } else { 00741 tab(n,fout); fout << "class " << fKlassName << " : public " << fSuperKlassName << " {"; 00742 } 00743 00744 if (gUIMacroSwitch) { 00745 tab(n,fout); fout << " public:"; 00746 } else { 00747 tab(n,fout); fout << " private:"; 00748 } 00749 00750 for (k = fSubClassList.begin(); k != fSubClassList.end(); k++) (*k)->println(n+1, fout); 00751 00752 printlines(n+1, fDeclCode, fout); 00753 00754 tab(n,fout); fout << " public:"; 00755 00756 printMetadata(n+1, gMetaDataSet, fout); 00757 00758 if (gSchedulerSwitch) { 00759 tab(n+1,fout); fout << "virtual ~" << fKlassName << "() \t{ " 00760 << "DSPThreadPool::Destroy()" 00761 << "; }"; 00762 } 00763 00764 tab(n+1,fout); fout << "virtual int getNumInputs() \t{ " 00765 << "return " << fNumInputs 00766 << "; }"; 00767 tab(n+1,fout); fout << "virtual int getNumOutputs() \t{ " 00768 << "return " << fNumOutputs 00769 << "; }"; 00770 00771 tab(n+1,fout); fout << "static void classInit(int samplingFreq) {"; 00772 printlines (n+2, fStaticInitCode, fout); 00773 tab(n+1,fout); fout << "}"; 00774 00775 tab(n+1,fout); fout << "virtual void instanceInit(int samplingFreq) {"; 00776 tab(n+2,fout); fout << "fSamplingFreq = samplingFreq;"; 00777 printlines (n+2, fInitCode, fout); 00778 tab(n+1,fout); fout << "}"; 00779 00780 tab(n+1,fout); fout << "virtual void init(int samplingFreq) {"; 00781 tab(n+2,fout); fout << "classInit(samplingFreq);"; 00782 tab(n+2,fout); fout << "instanceInit(samplingFreq);"; 00783 tab(n+1,fout); fout << "}"; 00784 00785 00786 tab(n+1,fout); fout << "virtual void buildUserInterface(UI* interface) {"; 00787 printlines (n+2, fUICode, fout); 00788 tab(n+1,fout); fout << "}"; 00789 00790 printComputeMethod(n, fout); 00791 00792 tab(n,fout); fout << "};\n" << endl; 00793 00794 printlines(n, fStaticFields, fout); 00795 00796 // generate user interface macros if needed 00797 if (gUIMacroSwitch) { 00798 tab(n, fout); fout << "#ifdef FAUST_UIMACROS"; 00799 tab(n+1,fout); fout << "#define FAUST_INPUTS " << fNumInputs; 00800 tab(n+1,fout); fout << "#define FAUST_OUTPUTS " << fNumOutputs; 00801 tab(n+1,fout); fout << "#define FAUST_ACTIVES " << fNumActives; 00802 tab(n+1,fout); fout << "#define FAUST_PASSIVES " << fNumPassives; 00803 printlines(n+1, fUIMacro, fout); 00804 tab(n, fout); fout << "#endif"; 00805 } 00806 00807 fout << endl; 00808 } 00809 00813 void Klass::printComputeMethod(int n, ostream& fout) 00814 { 00815 if (gSchedulerSwitch) { 00816 printComputeMethodScheduler (n, fout); 00817 } else if (gOpenMPSwitch) { 00818 printComputeMethodOpenMP (n, fout); 00819 } else if (gVectorSwitch) { 00820 switch (gVectorLoopVariant) { 00821 case 0 : printComputeMethodVectorFaster(n, fout); break; 00822 case 1 : printComputeMethodVectorSimple(n, fout); break; 00823 default : cerr << "unknown loop variant " << gVectorLoopVariant << endl; exit(1); 00824 } 00825 } else { 00826 printComputeMethodScalar(n, fout); 00827 } 00828 } 00829 00830 void Klass::printComputeMethodScalar(int n, ostream& fout) 00831 { 00832 tab(n+1,fout); fout << subst("virtual void compute (int count, $0** input, $0** output) {", xfloat()); 00833 printlines (n+2, fZone1Code, fout); 00834 printlines (n+2, fZone2Code, fout); 00835 printlines (n+2, fZone2bCode, fout); 00836 printlines (n+2, fZone3Code, fout); 00837 printLoopGraphScalar (n+2,fout); 00838 tab(n+1,fout); fout << "}"; 00839 } 00840 00846 void Klass::printComputeMethodVectorFaster(int n, ostream& fout) 00847 { 00848 // in vector mode we need to split loops in smaller pieces not larger 00849 // than gVecSize 00850 tab(n+1,fout); fout << subst("virtual void compute (int fullcount, $0** input, $0** output) {", xfloat()); 00851 printlines(n+2, fZone1Code, fout); 00852 printlines(n+2, fZone2Code, fout); 00853 printlines(n+2, fZone2bCode, fout); 00854 00855 tab(n+2,fout); fout << "int index;"; 00856 tab(n+2,fout); fout << "for (index = 0; index <= fullcount - " << gVecSize << "; index += " << gVecSize << ") {"; 00857 tab(n+3,fout); fout << "// compute by blocks of " << gVecSize << " samples"; 00858 tab(n+3,fout); fout << "const int count = " << gVecSize << ";"; 00859 printlines (n+3, fZone3Code, fout); 00860 printLoopGraphVector(n+3,fout); 00861 tab(n+2,fout); fout << "}"; 00862 00863 tab(n+2,fout); fout << "if (index < fullcount) {"; 00864 tab(n+3,fout); fout << "// compute the remaining samples if any"; 00865 tab(n+3,fout); fout << "int count = fullcount-index;"; 00866 printlines (n+3, fZone3Code, fout); 00867 printLoopGraphVector(n+3,fout); 00868 tab(n+2,fout); fout << "}"; 00869 tab(n+1,fout); fout << "}"; 00870 } 00871 00875 void Klass::printComputeMethodVectorSimple(int n, ostream& fout) 00876 { 00877 // in vector mode we need to split loops in smaller pieces not larger 00878 // than gVecSize 00879 tab(n+1,fout); fout << subst("virtual void compute (int fullcount, $0** input, $0** output) {", xfloat()); 00880 printlines(n+2, fZone1Code, fout); 00881 printlines(n+2, fZone2Code, fout); 00882 printlines(n+2, fZone2bCode, fout); 00883 tab(n+2,fout); fout << "for (int index = 0; index < fullcount; index += " << gVecSize << ") {"; 00884 tab(n+3,fout); fout << "int count = min("<< gVecSize << ", fullcount-index);"; 00885 printlines (n+3, fZone3Code, fout); 00886 printLoopGraphVector(n+3,fout); 00887 tab(n+2,fout); fout << "}"; 00888 tab(n+1,fout); fout << "}"; 00889 } 00890 00891 /* 00892 void Klass::printComputeMethodVectorFix0 (int n, ostream& fout) 00893 { 00894 // in vector mode we need to split loops in smaller pieces not larger 00895 // than gVecSize 00896 tab(n+1,fout); fout << "virtual void compute (int fullcount, float** input, float** output) {"; 00897 printlines(n+2, fZone1Code, fout); 00898 printlines(n+2, fZone2Code, fout); 00899 printlines(n+2, fZone2bCode, fout); 00900 tab(n+2,fout); fout << "for (int index = 0; index < fullcount; index += " << gVecSize << ") {"; 00901 tab(n+3,fout); fout << "if (fullcount >= index + " << gVecSize << ") {"; 00902 tab(n+4,fout); fout << "// compute by blocks of " << gVecSize << " samples"; 00903 tab(n+4,fout); fout << "const int count = " << gVecSize << ";"; // temporaire 00904 printlines(n+4, fZone3Code, fout); 00905 printLoopGraph (n+4,fout); 00906 tab(n+3,fout); fout << "} else if (fullcount > index) {"; 00907 //tab(n+3,fout); fout << "int count = min ("<< gVecSize << ", fullcount-index);"; 00908 tab(n+4,fout); fout << "// compute the remaining samples"; 00909 tab(n+4,fout); fout << "int count = fullcount-index;" ; 00910 printlines(n+4, fZone3Code, fout); 00911 printLoopGraph (n+4,fout); 00912 tab(n+3,fout); fout << "}"; 00913 tab(n+2,fout); fout << "}"; 00914 tab(n+1,fout); fout << "}"; 00915 } 00916 00917 void Klass::printComputeMethodVectorFix1 (int n, ostream& fout) 00918 { 00919 // in vector mode we need to split loops in smaller pieces not larger 00920 // than gVecSize 00921 tab(n+1,fout); fout << "virtual void compute (int fullcount, float** input, float** output) {"; 00922 printlines(n+2, fZone1Code, fout); 00923 printlines(n+2, fZone2Code, fout); 00924 printlines(n+2, fZone2bCode, fout); 00925 00926 tab(n+2,fout); fout << "int \tblock;"; 00927 tab(n+2,fout); fout << "for (block = 0; block < fullcount/" << gVecSize << "; block++) {"; 00928 tab(n+3,fout); fout << "// compute by blocks of " << gVecSize << " samples"; 00929 tab(n+3,fout); fout << "const int index = block*" << gVecSize << ";"; 00930 tab(n+3,fout); fout << "const int count = " << gVecSize << ";"; // temporaire 00931 printlines(n+3, fZone3Code, fout); 00932 printLoopGraph (n+3,fout); 00933 tab(n+2,fout); fout << "}"; 00934 00935 tab(n+2,fout); fout << "if (fullcount%" << gVecSize << " != 0) {"; 00936 //tab(n+3,fout); fout << "int count = min ("<< gVecSize << ", fullcount-index);"; 00937 tab(n+3,fout); fout << "// compute the remaining samples"; 00938 tab(n+3,fout); fout << "const int index = block*" << gVecSize << ";"; 00939 tab(n+3,fout); fout << "int count = fullcount%" << gVecSize << ";" ; 00940 printlines(n+3, fZone3Code, fout); 00941 printLoopGraph (n+3,fout); 00942 tab(n+2,fout); fout << "}"; 00943 tab(n+1,fout); fout << "}"; 00944 }*/ 00945 00946 void Klass::printComputeMethodOpenMP(int n, ostream& fout) 00947 { 00948 // in openMP mode we need to split loops in smaller pieces not larger 00949 // than gVecSize and add OpenMP pragmas 00950 tab(n+1,fout); fout << subst("virtual void compute (int fullcount, $0** input, $0** output) {", xfloat()); 00951 printlines(n+2, fZone1Code, fout); 00952 printlines(n+2, fZone2Code, fout); 00953 tab(n+2,fout); fout << "#pragma omp parallel"; 00954 printdecllist(n+3, "firstprivate", fFirstPrivateDecl, fout); 00955 00956 tab(n+2,fout); fout << "{"; 00957 if (!fZone2bCode.empty()) { 00958 tab(n+3,fout); fout << "#pragma omp single"; 00959 tab(n+3,fout); fout << "{"; 00960 printlines(n+4, fZone2bCode, fout); 00961 tab(n+3,fout); fout << "}"; 00962 } 00963 00964 tab(n+3,fout); fout << "for (int index = 0; index < fullcount; index += " << gVecSize << ") {"; 00965 tab(n+4,fout); fout << "int count = min ("<< gVecSize << ", fullcount-index);"; 00966 00967 printlines (n+4, fZone3Code, fout); 00968 printLoopGraphOpenMP (n+4,fout); 00969 00970 tab(n+3,fout); fout << "}"; 00971 00972 tab(n+2,fout); fout << "}"; 00973 tab(n+1,fout); fout << "}"; 00974 } 00975 00976 /* 00977 void Klass::printComputeMethodScheduler (int n, ostream& fout) 00978 { 00979 tab(n+1,fout); fout << subst("virtual void compute (int fullcount, $0** input, $0** output) {", xfloat()); 00980 printlines (n+2, fZone1Code, fout); 00981 printlines (n+2, fZone2Code, fout); 00982 00983 // Init input and output 00984 tab(n+2,fout); fout << "// Init input and output"; 00985 printlines (n+2, fZone3aCode, fout); 00986 printlines (n+2, fZone3bCode, fout); 00987 00988 tab(n+2,fout); fout << "// Init graph state"; 00989 tab(n+2,fout); fout << "initState(fTasksList);"; 00990 tab(n+2,fout); fout << "bool is_finished = false;"; 00991 tab(n+2,fout); fout << "unsigned int index_in = 0;"; 00992 tab(n+2,fout); fout << "unsigned int index_out = 0;"; 00993 tab(n+2,fout); fout << "int count = min ("<< gVecSize << ", fullcount);"; 00994 00995 tab(n+2,fout); fout << "InitSchedulingMap();"; 00996 tab(n+2,fout); fout << "#pragma omp parallel"; 00997 printdecllist(n+3, "firstprivate", fFirstPrivateDecl, fout); 00998 00999 tab(n+2,fout); fout << "{"; 01000 tab(n+3,fout); fout << "while (!is_finished) {"; 01001 tab(n+4,fout); fout << "Task* task = searchTaskToAcquire(fTasksList);"; 01002 tab(n+4,fout); fout << "if (task != NULL) {"; 01003 tab(n+5,fout); fout << "bool last_cycle_for_thread = false;"; 01004 tab(n+5,fout); fout << "do {"; 01005 tab(n+6,fout); fout << "AddTaskToScheduling(task);"; 01006 tab(n+6,fout); fout << "switch (task->fNum) {"; 01007 01008 // DSP tasks 01009 printLoopGraph (n+7,fout); 01010 01011 // Input task 01012 tab(n+7, fout); fout << "case " << gTaskCount++ << ": { "; 01013 printlines (n+8, fZone6Code, fout); 01014 tab(n+8, fout); fout << "index_in += count;"; 01015 tab(n+8, fout); fout << "last_cycle_for_thread = (index_in > fullcount);"; 01016 tab(n+8, fout); fout << "break;"; 01017 tab(n+7, fout); fout << "} "; 01018 01019 // Output task 01020 tab(n+7, fout); fout << "case " << gTaskCount++ << ": { "; 01021 printlines (n+8, fZone7Code, fout); 01022 tab(n+8, fout); fout << "index_out += count;"; 01023 tab(n+8, fout); fout << "last_cycle_for_thread = (index_out > fullcount);"; 01024 tab(n+8, fout); fout << "break;"; 01025 tab(n+7, fout); fout << "} "; 01026 01027 // End task 01028 tab(n+7, fout); fout << "case " << gTaskCount++ << ": { "; 01029 tab(n+8, fout); fout << "is_finished = ((index_in >= fullcount) && (index_out >= fullcount));"; 01030 tab(n+8, fout); fout << "break;"; 01031 tab(n+7, fout); fout << "} "; 01032 01033 tab(n+6,fout); fout << "}"; 01034 tab(n+6,fout); fout << "if (last_cycle_for_thread) break;"; 01035 01036 tab(n+5,fout); fout << "} while ((task = task->concludeAndTryToAcquireNext()) != NULL);"; 01037 tab(n+4,fout); fout << "}"; 01038 tab(n+3,fout); fout << "}"; 01039 tab(n+2,fout); fout << "}"; 01040 tab(n+2,fout); fout << "PrintSchedulingMap();"; 01041 tab(n+1,fout); fout << "}"; 01042 } 01043 */ 01044 01045 void Klass::printComputeMethodScheduler (int n, ostream& fout) 01046 { 01047 tab(n+1,fout); fout << "void display() {"; 01048 tab(n+2,fout); fout << "fGraph.Display();"; 01049 tab(n+1,fout); fout << "}"; 01050 01051 tab(n+1,fout); fout << subst("virtual void compute (int fullcount, $0** input, $0** output) {", xfloat()); 01052 01053 tab(n+2,fout); fout << "GetRealTime();"; 01054 01055 tab(n+2,fout); fout << "this->input = input;"; 01056 tab(n+2,fout); fout << "this->output = output;"; 01057 01058 tab(n+2,fout); fout << "StartMeasure();"; 01059 01060 tab(n+2,fout); fout << "for (fIndex = 0; fIndex < fullcount; fIndex += " << gVecSize << ") {"; 01061 01062 tab(n+3,fout); fout << "fFullCount = min ("<< gVecSize << ", fullcount-fIndex);"; 01063 tab(n+3,fout); fout << "TaskQueue::Init();"; 01064 printlines (n+3, fZone2cCode, fout); 01065 01066 tab(n+3,fout); fout << "fIsFinished = false;"; 01067 tab(n+3,fout); fout << "fThreadPool->SignalAll(fDynamicNumThreads - 1, this);"; 01068 tab(n+3,fout); fout << "computeThread(0);"; 01069 tab(n+3,fout); fout << "while (!fThreadPool->IsFinished()) {}"; 01070 01071 tab(n+2,fout); fout << "}"; 01072 01073 tab(n+2,fout); fout << "StopMeasure(fStaticNumThreads, fDynamicNumThreads);"; 01074 01075 tab(n+1,fout); fout << "}"; 01076 01077 tab(n+1,fout); fout << "void computeThread(int cur_thread) {"; 01078 printlines (n+2, fZone1Code, fout); 01079 printlines (n+2, fZone2Code, fout); 01080 01081 tab(n+2,fout); fout << "// Init graph state"; 01082 01083 tab(n+2,fout); fout << "{"; 01084 tab(n+3,fout); fout << "TaskQueue taskqueue(cur_thread);"; 01085 tab(n+3,fout); fout << "int tasknum = -1;"; 01086 tab(n+3,fout); fout << "int count = fFullCount;"; 01087 01088 // Init input and output 01089 tab(n+3,fout); fout << "// Init input and output"; 01090 printlines (n+3, fZone3Code, fout); 01091 01092 tab(n+3,fout); fout << "while (!fIsFinished) {"; 01093 tab(n+4,fout); fout << "switch (tasknum) {"; 01094 01095 // Work stealing task 01096 tab(n+5, fout); fout << "case WORK_STEALING_INDEX: { "; 01097 tab(n+6, fout); fout << "tasknum = TaskQueue::GetNextTask(cur_thread, fDynamicNumThreads);"; 01098 tab(n+6, fout); fout << "break;"; 01099 tab(n+5, fout); fout << "} "; 01100 01101 // End task 01102 tab(n+5, fout); fout << "case LAST_TASK_INDEX: { "; 01103 tab(n+6, fout); fout << "fIsFinished = true;"; 01104 tab(n+6, fout); fout << "break;"; 01105 tab(n+5, fout); fout << "} "; 01106 01107 gTaskCount = START_TASK_INDEX; 01108 01109 // DSP tasks 01110 printLoopGraphScheduler (n+5,fout); 01111 01112 tab(n+4,fout); fout << "}"; 01113 tab(n+3,fout); fout << "}"; 01114 tab(n+2,fout); fout << "}"; 01115 tab(n+1,fout); fout << "}"; 01116 } 01117 01121 void SigIntGenKlass::println(int n, ostream& fout) 01122 { 01123 list<Klass* >::iterator k; 01124 01125 tab(n,fout); fout << "class " << fKlassName << " {"; 01126 01127 tab(n,fout); fout << " private:"; 01128 tab(n+1,fout); fout << "int \tfSamplingFreq;"; 01129 01130 for (k = fSubClassList.begin(); k != fSubClassList.end(); k++) (*k)->println(n+1, fout); 01131 01132 printlines(n+1, fDeclCode, fout); 01133 01134 tab(n,fout); fout << " public:"; 01135 01136 tab(n+1,fout); fout << "int getNumInputs() \t{ " 01137 << "return " << fNumInputs << "; }"; 01138 tab(n+1,fout); fout << "int getNumOutputs() \t{ " 01139 << "return " << fNumOutputs << "; }"; 01140 01141 tab(n+1,fout); fout << "void init(int samplingFreq) {"; 01142 tab(n+2,fout); fout << "fSamplingFreq = samplingFreq;"; 01143 tab(n+1,fout); fout << "}"; 01144 01145 tab(n+1,fout); fout << "void fill (int count, int output[]) {"; 01146 printlines (n+2, fZone1Code, fout); 01147 printlines (n+2, fZone2Code, fout); 01148 printlines (n+2, fZone2bCode, fout); 01149 printlines (n+2, fZone3Code, fout); 01150 printLoopGraphInternal (n+2,fout); 01151 tab(n+1,fout); fout << "}"; 01152 01153 tab(n,fout); fout << "};\n" << endl; 01154 } 01155 01159 void SigFloatGenKlass::println(int n, ostream& fout) 01160 { 01161 list<Klass* >::iterator k; 01162 01163 tab(n,fout); fout << "class " << fKlassName << " {"; 01164 01165 tab(n,fout); fout << " private:"; 01166 tab(n+1,fout); fout << "int \tfSamplingFreq;"; 01167 01168 for (k = fSubClassList.begin(); k != fSubClassList.end(); k++) (*k)->println(n+1, fout); 01169 01170 printlines(n+1, fDeclCode, fout); 01171 01172 tab(n,fout); fout << " public:"; 01173 01174 tab(n+1,fout); fout << "int getNumInputs() \t{ " 01175 << "return " << fNumInputs << "; }"; 01176 tab(n+1,fout); fout << "int getNumOutputs() \t{ " 01177 << "return " << fNumOutputs << "; }"; 01178 01179 tab(n+1,fout); fout << "void init(int samplingFreq) {"; 01180 tab(n+2,fout); fout << "fSamplingFreq = samplingFreq;"; 01181 printlines(n+2, fInitCode, fout); 01182 tab(n+1,fout); fout << "}"; 01183 01184 tab(n+1,fout); fout << subst("void fill (int count, $0 output[]) {", ifloat()); 01185 printlines (n+2, fZone1Code, fout); 01186 printlines (n+2, fZone2Code, fout); 01187 printlines (n+2, fZone2bCode, fout); 01188 printlines (n+2, fZone3Code, fout); 01189 printLoopGraphInternal(n+2,fout); 01190 tab(n+1,fout); fout << "}"; 01191 01192 tab(n,fout); fout << "};\n" << endl; 01193 } 01194 01195 static void merge (set<string>& dst, set<string>& src) 01196 { 01197 set<string>::iterator i; 01198 for (i = src.begin(); i != src.end(); i++) dst.insert(*i); 01199 } 01200 01201 void Klass::collectIncludeFile(set<string>& S) 01202 { 01203 list<Klass* >::iterator k; 01204 01205 for (k = fSubClassList.begin(); k != fSubClassList.end(); k++) (*k)->collectIncludeFile(S); 01206 merge(S, fIncludeFileSet); 01207 } 01208 01209 void Klass::collectLibrary(set<string>& S) 01210 { 01211 list<Klass* >::iterator k; 01212 01213 for (k = fSubClassList.begin(); k != fSubClassList.end(); k++) (*k)->collectLibrary(S); 01214 merge(S, fLibrarySet); 01215 }
1.8.0