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