00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #define FAUSTVERSION "0.9.24"
00022
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <assert.h>
00026
00027 #ifndef WIN32
00028 #include <sys/time.h>
00029 #include "libgen.h"
00030 #endif
00031
00032 #include "compatibility.hh"
00033 #include "signals.hh"
00034 #include "sigtype.hh"
00035 #include "sigtyperules.hh"
00036 #include "sigprint.hh"
00037 #include "simplify.hh"
00038 #include "privatise.hh"
00039
00040 #include "compile_scal.hh"
00041 #include "compile_vect.hh"
00042 #include "compile_sched.hh"
00043
00044 #include "propagate.hh"
00045 #include "errormsg.hh"
00046 #include "ppbox.hh"
00047 #include "enrobage.hh"
00048 #include "eval.hh"
00049 #include "description.hh"
00050 #include "floats.hh"
00051 #include "doc.hh"
00052
00053 #include <map>
00054 #include <string>
00055 #include <vector>
00056 #include <iostream>
00057 #include <fstream>
00058 #include <sstream>
00059
00060 #ifndef WIN32
00061 #include <unistd.h>
00062 #endif
00063
00064 #include "sourcereader.hh"
00065
00066
00067
00068
00069 #include "schema.h"
00070 #include "drawschema.hh"
00071 #include "timing.hh"
00072
00073 using namespace std ;
00074
00075
00076
00077
00078
00079
00080
00081 int yyparse();
00082
00083 int yyerr;
00084 extern int yydebug;
00085 extern FILE* yyin;
00086 Tree gResult;
00087 Tree gResult2;
00088
00089 SourceReader gReader;
00090
00091 map<Tree, set<Tree> > gMetaDataSet;
00092 extern vector<Tree> gDocVector;
00093 extern string gDocLang;
00094
00095
00096
00097
00098
00099
00100
00101 string gFaustSuperSuperDirectory;
00102 string gFaustSuperDirectory;
00103 string gFaustDirectory;
00104 string gMasterDocument;
00105 string gMasterDirectory;
00106 string gMasterName;
00107 string gDocName;
00108 Tree gExpandedDefList;
00109
00110
00111
00112 bool gHelpSwitch = false;
00113 bool gVersionSwitch = false;
00114 bool gDetailsSwitch = false;
00115 bool gShadowBlur = false;
00116 bool gGraphSwitch = false;
00117 bool gDrawPSSwitch = false;
00118 bool gDrawSVGSwitch = false;
00119 bool gPrintXMLSwitch = false;
00120 bool gPrintDocSwitch = false;
00121 bool gLatexDocSwitch = true;
00122 bool gStripDocSwitch = false;
00123 int gBalancedSwitch = 0;
00124 int gFoldThreshold = 25;
00125 int gMaxNameSize = 40;
00126 bool gSimpleNames = false;
00127 bool gSimplifyDiagrams = false;
00128 bool gLessTempSwitch = false;
00129 int gMaxCopyDelay = 16;
00130 string gArchFile;
00131 string gOutputFile;
00132 list<string> gInputFiles;
00133
00134 bool gPatternEvalMode = false;
00135
00136 bool gVectorSwitch = false;
00137 bool gDeepFirstSwitch= false;
00138 int gVecSize = 32;
00139 int gVectorLoopVariant = 0;
00140
00141 bool gOpenMPSwitch = false;
00142 bool gSchedulerSwitch = false;
00143 bool gGroupTaskSwitch= false;
00144
00145 bool gUIMacroSwitch = false;
00146
00147 int gTimeout = 0;
00148
00149 int gFloatSize = 1;
00150
00151 bool gPrintFileListSwitch = false;
00152
00153
00154
00155 static bool isCmd(const char* cmd, const char* kw1)
00156 {
00157 return (strcmp(cmd, kw1) == 0);
00158 }
00159
00160 static bool isCmd(const char* cmd, const char* kw1, const char* kw2)
00161 {
00162 return (strcmp(cmd, kw1) == 0) || (strcmp(cmd, kw2) == 0);
00163 }
00164
00165 bool process_cmdline(int argc, char* argv[])
00166 {
00167 int i=1; int err=0;
00168
00169 while (i<argc) {
00170
00171 if (isCmd(argv[i], "-h", "--help")) {
00172 gHelpSwitch = true;
00173 i += 1;
00174
00175 } else if (isCmd(argv[i], "-v", "--version")) {
00176 gVersionSwitch = true;
00177 i += 1;
00178
00179 } else if (isCmd(argv[i], "-d", "--details")) {
00180 gDetailsSwitch = true;
00181 i += 1;
00182
00183 } else if (isCmd(argv[i], "-a", "--architecture")) {
00184 gArchFile = argv[i+1];
00185 i += 2;
00186
00187 } else if (isCmd(argv[i], "-o")) {
00188 gOutputFile = argv[i+1];
00189 i += 2;
00190
00191 } else if (isCmd(argv[i], "-ps", "--postscript")) {
00192 gDrawPSSwitch = true;
00193 i += 1;
00194
00195 } else if (isCmd(argv[i], "-xml", "--xml")) {
00196 gPrintXMLSwitch = true;
00197 i += 1;
00198
00199 } else if (isCmd(argv[i], "-tg", "--task-graph")) {
00200 gGraphSwitch = true;
00201 i += 1;
00202
00203 } else if (isCmd(argv[i], "-blur", "--shadow-blur")) {
00204 gShadowBlur = true;
00205 i += 1;
00206
00207 } else if (isCmd(argv[i], "-svg", "--svg")) {
00208 gDrawSVGSwitch = true;
00209 i += 1;
00210
00211 } else if (isCmd(argv[i], "-f", "--fold")) {
00212 gFoldThreshold = atoi(argv[i+1]);
00213 i += 2;
00214
00215 } else if (isCmd(argv[i], "-mns", "--max-name-size")) {
00216 gMaxNameSize = atoi(argv[i+1]);
00217 i += 2;
00218
00219 } else if (isCmd(argv[i], "-sn", "--simple-names")) {
00220 gSimpleNames = true;
00221 i += 1;
00222
00223 } else if (isCmd(argv[i], "-lb", "--left-balanced")) {
00224 gBalancedSwitch = 0;
00225 i += 1;
00226
00227 } else if (isCmd(argv[i], "-mb", "--mid-balanced")) {
00228 gBalancedSwitch = 1;
00229 i += 1;
00230
00231 } else if (isCmd(argv[i], "-rb", "--right-balanced")) {
00232 gBalancedSwitch = 2;
00233 i += 1;
00234
00235 } else if (isCmd(argv[i], "-lt", "--less-temporaries")) {
00236 gLessTempSwitch = true;
00237 i += 1;
00238
00239 } else if (isCmd(argv[i], "-mcd", "--max-copy-delay")) {
00240 gMaxCopyDelay = atoi(argv[i+1]);
00241 i += 2;
00242
00243 } else if (isCmd(argv[i], "-sd", "--simplify-diagrams")) {
00244 gSimplifyDiagrams = true;
00245 i += 1;
00246
00247 } else if (isCmd(argv[i], "-vec", "--vectorize")) {
00248 gVectorSwitch = true;
00249 i += 1;
00250
00251 } else if (isCmd(argv[i], "-dfs", "--deepFirstScheduling")) {
00252 gDeepFirstSwitch = true;
00253 i += 1;
00254
00255 } else if (isCmd(argv[i], "-vs", "--vec-size")) {
00256 gVecSize = atoi(argv[i+1]);
00257 i += 2;
00258
00259 } else if (isCmd(argv[i], "-lv", "--loop-variant")) {
00260 gVectorLoopVariant = atoi(argv[i+1]);
00261 i += 2;
00262
00263 } else if (isCmd(argv[i], "-omp", "--openMP")) {
00264 gOpenMPSwitch = true;
00265 i += 1;
00266
00267 } else if (isCmd(argv[i], "-sch", "--scheduler")) {
00268 gSchedulerSwitch = true;
00269 i += 1;
00270
00271 } else if (isCmd(argv[i], "-g", "--groupTasks")) {
00272 gGroupTaskSwitch = true;
00273 i += 1;
00274
00275 } else if (isCmd(argv[i], "-uim", "--user-interface-macros")) {
00276 gUIMacroSwitch = true;
00277 i += 1;
00278
00279 } else if (isCmd(argv[i], "-t", "--timeout")) {
00280 gTimeout = atoi(argv[i+1]);
00281 i += 2;
00282
00283
00284 } else if (isCmd(argv[i], "-single", "--single-precision-floats")) {
00285 gFloatSize = 1;
00286 i += 1;
00287
00288 } else if (isCmd(argv[i], "-double", "--double-precision-floats")) {
00289 gFloatSize = 2;
00290 i += 1;
00291
00292 } else if (isCmd(argv[i], "-quad", "--quad-precision-floats")) {
00293 gFloatSize = 3;
00294 i += 1;
00295
00296 } else if (isCmd(argv[i], "-mdoc", "--mathdoc")) {
00297 gPrintDocSwitch = true;
00298 i += 1;
00299
00300 } else if (isCmd(argv[i], "-mdlang", "--mathdoc-lang")) {
00301 gDocLang = argv[i+1];
00302 i += 2;
00303
00304 } else if (isCmd(argv[i], "-stripmdoc", "--strip-mdoc-tags")) {
00305 gStripDocSwitch = true;
00306 i += 1;
00307
00308 } else if (isCmd(argv[i], "-flist", "--file-list")) {
00309 gPrintFileListSwitch = true;
00310 i += 1;
00311
00312 } else if (argv[i][0] != '-') {
00313 if (check_file(argv[i])) {
00314 gInputFiles.push_back(argv[i]);
00315 }
00316 i++;
00317
00318 } else {
00319 cerr << "faust: unrecognized option \"" << argv[i] <<"\"" << endl;
00320 i++;
00321 err++;
00322 }
00323 }
00324
00325
00326 if (gOpenMPSwitch || gSchedulerSwitch) gVectorSwitch = true;
00327
00328 return err == 0;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 void printversion()
00340 {
00341 cout << "FAUST, DSP to C++ compiler, Version " << FAUSTVERSION << "\n";
00342 cout << "Copyright (C) 2002-2010, GRAME - Centre National de Creation Musicale. All rights reserved. \n\n";
00343 }
00344
00345
00346 void printhelp()
00347 {
00348 printversion();
00349 cout << "usage: faust [options] file1 [file2 ...]\n";
00350 cout << "\twhere options represent zero or more compiler options \n\tand fileN represents a faust source file (.dsp extension).\n";
00351
00352 cout << "\noptions :\n";
00353 cout << "---------\n";
00354
00355 cout << "-h \t\tprint this --help message\n";
00356 cout << "-v \t\tprint compiler --version information\n";
00357 cout << "-d \t\tprint compilation --details\n";
00358 cout << "-tg \t\tprint the internal --task-graph in dot format file\n";
00359 cout << "-ps \t\tprint block-diagram --postscript file\n";
00360 cout << "-svg \tprint block-diagram --svg file\n";
00361 cout << "-mdoc \tprint --mathdoc of a Faust program in LaTeX format in a -mdoc directory\n";
00362 cout << "-mdlang <l>\t\tload --mathdoc-lang <l> if translation file exists (<l> = en, fr, ...)\n";
00363 cout << "-stripdoc \t\tapply --strip-mdoc-tags when printing Faust -mdoc listings\n";
00364 cout << "-sd \t\ttry to further --simplify-diagrams before drawing them\n";
00365 cout << "-f <n> \t\t--fold <n> threshold during block-diagram generation (default 25 elements) \n";
00366 cout << "-mns <n> \t--max-name-size <n> threshold during block-diagram generation (default 40 char)\n";
00367 cout << "-sn \t\tuse --simple-names (without arguments) during block-diagram generation\n";
00368 cout << "-xml \t\tgenerate an --xml description file\n";
00369 cout << "-blur \t\tadd a --shadow-blur to SVG boxes\n";
00370 cout << "-lb \t\tgenerate --left-balanced expressions\n";
00371 cout << "-mb \t\tgenerate --mid-balanced expressions (default)\n";
00372 cout << "-rb \t\tgenerate --right-balanced expressions\n";
00373 cout << "-lt \t\tgenerate --less-temporaries in compiling delays\n";
00374 cout << "-mcd <n> \t--max-copy-delay <n> threshold between copy and ring buffer implementation (default 16 samples)\n";
00375 cout << "-a <file> \tC++ architecture file\n";
00376 cout << "-o <file> \tC++ output file\n";
00377 cout << "-vec \t--vectorize generate easier to vectorize code\n";
00378 cout << "-vs <n> \t--vec-size <n> size of the vector (default 32 samples)\n";
00379 cout << "-lv <n> \t--loop-variant [0:fastest (default), 1:simple] \n";
00380 cout << "-omp \t--openMP generate OpenMP pragmas, activates --vectorize option\n";
00381 cout << "-sch \t--scheduler generate tasks and use a Work Stealing scheduler, activates --vectorize option\n";
00382 cout << "-dfs \t--deepFirstScheduling schedule vector loops in deep first order\n";
00383 cout << "-g \t\t--groupTasks group single-threaded sequential tasks together when -omp or -sch is used\n";
00384 cout << "-uim \t--user-interface-macros add user interface macro definitions in the C++ code\n";
00385 cout << "-single \tuse --single-precision-floats for internal computations (default)\n";
00386 cout << "-double \tuse --double-precision-floats for internal computations\n";
00387 cout << "-quad \t\tuse --quad-precision-floats for internal computations\n";
00388 cout << "-flist \t\tuse --file-list used to eval process\n";
00389
00390 cout << "\nexample :\n";
00391 cout << "---------\n";
00392
00393 cout << "faust -a jack-gtk.cpp -o myfx.cpp myfx.dsp\n";
00394 }
00395
00396
00397 void printheader(ostream& dst)
00398 {
00399
00400 set<Tree> selectedKeys;
00401 selectedKeys.insert(tree("name"));
00402 selectedKeys.insert(tree("author"));
00403 selectedKeys.insert(tree("copyright"));
00404 selectedKeys.insert(tree("license"));
00405 selectedKeys.insert(tree("version"));
00406
00407 dst << "//-----------------------------------------------------" << endl;
00408 for (map<Tree, set<Tree> >::iterator i = gMetaDataSet.begin(); i != gMetaDataSet.end(); i++) {
00409 if (selectedKeys.count(i->first)) {
00410 dst << "// " << *(i->first);
00411 const char* sep = ": ";
00412 for (set<Tree>::iterator j = i->second.begin(); j != i->second.end(); ++j) {
00413 dst << sep << **j;
00414 sep = ", ";
00415 }
00416 dst << endl;
00417 }
00418 }
00419
00420 dst << "//" << endl;
00421 dst << "// Code generated with Faust " << FAUSTVERSION << " (http://faust.grame.fr)" << endl;
00422 dst << "//-----------------------------------------------------" << endl;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 static string dirname(const string& path)
00434 {
00435 char s[1024];
00436 strncpy(s, path.c_str(), 1024);
00437 return string(dirname(s));
00438 }
00439
00444 static string fxname(const string& filename)
00445 {
00446
00447 unsigned int p1 = 0;
00448 for (unsigned int i=0; i<filename.size(); i++) {
00449 if (filename[i] == '/') { p1 = i+1; }
00450 }
00451
00452
00453 unsigned int p2 = filename.size();
00454 for (unsigned int i=p1; i<filename.size(); i++) {
00455 if (filename[i] == '.') { p2 = i; }
00456 }
00457
00458 return filename.substr(p1, p2-p1);
00459 }
00460
00461
00462 static void initFaustDirectories()
00463 {
00464 char s[1024];
00465 getFaustPathname(s, 1024);
00466 dirname(s);
00467 gFaustDirectory = s;
00468 gFaustSuperDirectory = dirname(gFaustDirectory);
00469 gFaustSuperSuperDirectory = dirname(gFaustSuperDirectory);
00470 if (gInputFiles.empty()) {
00471 gMasterDocument = "Unknown";
00472 gMasterDirectory = ".";
00473 gMasterName = "faustfx";
00474 gDocName = "faustdoc";
00475 } else {
00476 gMasterDocument = *gInputFiles.begin();
00477 gMasterDirectory = dirname(gMasterDocument);
00478 gMasterName = fxname(gMasterDocument);
00479 gDocName = fxname(gMasterDocument);
00480 }
00481 }
00482
00483
00484
00485 int main (int argc, char* argv[])
00486 {
00487
00488
00489
00490
00491
00492 process_cmdline(argc, argv);
00493
00494 if (gHelpSwitch) { printhelp(); exit(0); }
00495 if (gVersionSwitch) { printversion(); exit(0); }
00496
00497 initFaustDirectories();
00498 #ifndef WIN32
00499 alarm(gTimeout);
00500 #endif
00501
00502
00503
00504
00505
00506
00507 startTiming("parser");
00508
00509
00510 list<string>::iterator s;
00511 gResult2 = nil;
00512 yyerr = 0;
00513
00514 if (gInputFiles.begin() == gInputFiles.end()) {
00515 cerr << "ERROR: no files specified; for help type \"faust --help\"" << endl;
00516 exit(1);
00517 }
00518 for (s = gInputFiles.begin(); s != gInputFiles.end(); s++) {
00519 if (s == gInputFiles.begin()) gMasterDocument = *s;
00520 gResult2 = cons(importFile(tree(s->c_str())), gResult2);
00521 }
00522 if (yyerr > 0) {
00523
00524 exit(1);
00525 }
00526 gExpandedDefList = gReader.expandlist(gResult2);
00527
00528 endTiming("parser");
00529
00530
00531
00532
00533
00534 startTiming("evaluation");
00535
00536
00537 Tree process = evalprocess(gExpandedDefList);
00538 if (gErrorCount > 0) {
00539
00540 cerr << "Total of " << gErrorCount << " errors during the compilation of " << gMasterDocument << ";\n";
00541 exit(1);
00542 }
00543
00544
00545 if (gDetailsSwitch) { cerr << "process = " << boxpp(process) << ";\n"; }
00546
00547 if (gDrawPSSwitch || gDrawSVGSwitch) {
00548 string projname = gMasterDocument;
00549 if( gMasterDocument.substr(gMasterDocument.length()-4) == ".dsp" ) {
00550 projname = gMasterDocument.substr(0, gMasterDocument.length()-4);
00551 }
00552 if (gDrawPSSwitch) { drawSchema( process, subst("$0-ps", projname).c_str(), "ps" ); }
00553 if (gDrawSVGSwitch) { drawSchema( process, subst("$0-svg", projname).c_str(), "svg" ); }
00554 }
00555
00556 int numInputs, numOutputs;
00557 if (!getBoxType(process, &numInputs, &numOutputs)) {
00558 cerr << "ERROR during the evaluation of process : "
00559 << boxpp(process) << endl;
00560 exit(1);
00561 }
00562
00563 if (gDetailsSwitch) {
00564 cerr <<"process has " << numInputs <<" inputs, and " << numOutputs <<" outputs" << endl;
00565 }
00566
00567 endTiming("evaluation");
00568
00569
00570
00571
00572
00573 if (gPrintFileListSwitch) {
00574 cout << "******* ";
00575
00576 vector<string> pathnames = gReader.listSrcFiles();
00577 for (unsigned int i=0; i< pathnames.size(); i++) cout << pathnames[i] << ' ';
00578 cout << endl;
00579
00580 }
00581
00582
00583
00584
00585
00586
00587 startTiming("propagation");
00588
00589
00590 Tree lsignals = boxPropagateSig(nil, process , makeSigInputList(numInputs) );
00591 if (gDetailsSwitch) { cerr << "output signals are : " << endl; printSignal(lsignals, stderr); }
00592
00593 endTiming("propagation");
00594
00595
00596
00597
00598
00599
00600 startTiming("compilation");
00601
00602 Compiler* C;
00603 if (gSchedulerSwitch) C = new SchedulerCompiler("mydsp", "dsp", numInputs, numOutputs);
00604 else if (gVectorSwitch) C = new VectorCompiler("mydsp", "dsp", numInputs, numOutputs);
00605 else C = new ScalarCompiler("mydsp", "dsp", numInputs, numOutputs);
00606
00607 if (gPrintXMLSwitch) C->setDescription(new Description());
00608 if (gPrintDocSwitch) C->setDescription(new Description());
00609
00610 C->compileMultiSignal(lsignals);
00611
00612 endTiming("compilation");
00613
00614
00615
00616
00617
00618 if (gPrintXMLSwitch) {
00619 Description* D = C->getDescription(); assert(D);
00620
00621 ofstream xout(subst("$0.xml", gMasterDocument).c_str());
00622
00623 if(gMetaDataSet.count(tree("name"))>0) D->name(tree2str(*(gMetaDataSet[tree("name")].begin())));
00624 if(gMetaDataSet.count(tree("author"))>0) D->author(tree2str(*(gMetaDataSet[tree("author")].begin())));
00625 if(gMetaDataSet.count(tree("copyright"))>0) D->copyright(tree2str(*(gMetaDataSet[tree("copyright")].begin())));
00626 if(gMetaDataSet.count(tree("license"))>0) D->license(tree2str(*(gMetaDataSet[tree("license")].begin())));
00627 if(gMetaDataSet.count(tree("version"))>0) D->version(tree2str(*(gMetaDataSet[tree("version")].begin())));
00628
00629 D->inputs(C->getClass()->inputs());
00630 D->outputs(C->getClass()->outputs());
00631
00632 D->print(0, xout);
00633 }
00634
00635
00636
00637
00638
00639
00640
00641 if (gPrintDocSwitch) {
00642 if (gLatexDocSwitch) {
00643 string projname = gMasterDocument;
00644 if( gMasterDocument.substr(gMasterDocument.length()-4) == ".dsp" ) {
00645 projname = gMasterDocument.substr(0, gMasterDocument.length()-4); }
00646 printDoc( subst("$0-mdoc", projname).c_str(), "tex", FAUSTVERSION );
00647 }
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657 ostream* dst;
00658 istream* enrobage;
00659
00660
00661 if (gOutputFile != "") {
00662 dst = new ofstream(gOutputFile.c_str());
00663 } else {
00664 dst = &cout;
00665 }
00666
00667 if (gArchFile != "") {
00668 if ( (enrobage = open_arch_stream(gArchFile.c_str())) ) {
00669 printheader(*dst);
00670 C->getClass()->printLibrary(*dst);
00671 C->getClass()->printIncludeFile(*dst);
00672 C->getClass()->printAdditionalCode(*dst);
00673
00674 streamCopyUntil(*enrobage, *dst, "<<includeIntrinsic>>");
00675
00676
00677
00678
00679
00680 if (gSchedulerSwitch) {
00681 istream* scheduler_include = open_arch_stream("scheduler.h");
00682 if (scheduler_include) {
00683 streamCopy(*scheduler_include, *dst);
00684 }
00685 }
00686
00687 streamCopyUntil(*enrobage, *dst, "<<includeclass>>");
00688 printfloatdef(*dst);
00689
00690 C->getClass()->println(0,*dst);
00691 streamCopyUntilEnd(*enrobage, *dst);
00692 } else {
00693 cerr << "ERROR : can't open architecture file " << gArchFile << endl;
00694 return 1;
00695 }
00696 } else {
00697 printheader(*dst);
00698 printfloatdef(*dst);
00699 C->getClass()->printLibrary(*dst);
00700 C->getClass()->printIncludeFile(*dst);
00701 C->getClass()->printAdditionalCode(*dst);
00702 C->getClass()->println(0,*dst);
00703 }
00704
00705
00706
00707
00708
00709
00710 if (gGraphSwitch) {
00711 ofstream dotfile(subst("$0.dot", gMasterDocument).c_str());
00712 C->getClass()->printGraphDotFormat(dotfile);
00713 }
00714
00715
00716
00717
00718 delete C;
00719 return 0;
00720 }