00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "compile_scal.hh"
00029 #include "timing.hh"
00030
00031 #include "compile.hh"
00032 #include "sigtype.hh"
00033
00034 #include <stdio.h>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <vector>
00038 #include <math.h>
00039
00040 #include "floats.hh"
00041 #include "sigprint.hh"
00042 #include "sigtyperules.hh"
00043 #include "recursivness.hh"
00044 #include "simplify.hh"
00045 #include "privatise.hh"
00046 #include "prim2.hh"
00047 #include "xtended.hh"
00048
00049 #include "compatibility.hh"
00050 #include "ppsig.hh"
00051
00052 extern bool gLessTempSwitch;
00053 extern int gMaxCopyDelay;
00054
00055 static Klass* signal2klass (const string& name, Tree sig)
00056 {
00057 Type t = getSigType(sig);
00058 if (t->nature() == kInt) {
00059
00060 ScalarCompiler C( new SigIntGenKlass(name) );
00061 C.compileSingleSignal(sig);
00062 return C.getClass();
00063
00064 } else {
00065
00066 ScalarCompiler C( new SigFloatGenKlass(name) );
00067 C.compileSingleSignal(sig);
00068 return C.getClass();
00069
00070 }
00071 }
00072
00073
00074
00075
00076
00077
00078 map<string, int> ScalarCompiler::fIDCounters;
00079
00080 string ScalarCompiler::getFreshID(const string& prefix)
00081 {
00082 if (fIDCounters.find(prefix) == fIDCounters.end()) {
00083 fIDCounters[prefix]=0;
00084 }
00085 int n = fIDCounters[prefix];
00086 fIDCounters[prefix] = n+1;
00087 return subst("$0$1", prefix, T(n));
00088 }
00089
00090
00091
00092
00093
00094
00095 Tree ScalarCompiler::prepare(Tree LS)
00096 {
00097 startTiming("ScalarCompiler::prepare");
00098 startTiming("deBruijn2Sym");
00099 Tree L1 = deBruijn2Sym(LS);
00100 endTiming("deBruijn2Sym");
00101 Tree L2 = simplify(L1);
00102 Tree L3 = privatise(L2);
00103
00104 recursivnessAnnotation(L3);
00105 typeAnnotation(L3);
00106 sharingAnalysis(L3);
00107 fOccMarkup.mark(L3);
00108 endTiming("ScalarCompiler::prepare");
00109 return L3;
00110 }
00111
00112 Tree ScalarCompiler::prepare2(Tree L0)
00113 {
00114 startTiming("ScalarCompiler::prepare2");
00115 recursivnessAnnotation(L0);
00116 typeAnnotation(L0);
00117 sharingAnalysis(L0);
00118 fOccMarkup.mark(L0);
00119 endTiming("ScalarCompiler::prepare2");
00120
00121 return L0;
00122 }
00123
00124
00125
00126
00127
00128 void ScalarCompiler::compileMultiSignal (Tree L)
00129 {
00130
00131 L = prepare(L);
00132
00133 for (int i = 0; i < fClass->inputs(); i++) {
00134 fClass->addZone3(subst("$1* input$0 = input[$0];", T(i), xfloat()));
00135 }
00136 for (int i = 0; i < fClass->outputs(); i++) {
00137 fClass->addZone3(subst("$1* output$0 = output[$0];", T(i), xfloat()));
00138 }
00139
00140 for (int i = 0; isList(L); L = tl(L), i++) {
00141 Tree sig = hd(L);
00142 fClass->addExecCode(subst("output$0[i] = $2$1;", T(i), CS(sig), xcast()));
00143 }
00144 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
00145 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
00146 if (fDescription) {
00147 fDescription->ui(prepareUserInterfaceTree(fUIRoot));
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156 void ScalarCompiler::compileSingleSignal (Tree sig)
00157 {
00158
00159 sig = prepare2(sig);
00160 fClass->addExecCode(subst("output[i] = $0;", CS(sig)));
00161 generateUserInterfaceTree(prepareUserInterfaceTree(fUIRoot));
00162 generateMacroInterfaceTree("", prepareUserInterfaceTree(fUIRoot));
00163 if (fDescription) {
00164 fDescription->ui(prepareUserInterfaceTree(fUIRoot));
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00179 bool ScalarCompiler::getCompiledExpression(Tree sig, string& cexp)
00180 {
00181 return fCompileProperty.get(sig, cexp);
00182 }
00183
00190 string ScalarCompiler::setCompiledExpression(Tree sig, const string& cexp)
00191 {
00192 fCompileProperty.set(sig, cexp);
00193 return cexp;
00194 }
00195
00201 string ScalarCompiler::CS (Tree sig)
00202 {
00203
00204 string code;
00205
00206 if (!getCompiledExpression(sig, code)) {
00207
00208
00209
00210
00211 code = generateCode(sig);
00212 setCompiledExpression(sig, code);
00213 }
00214 return code;
00215 }
00216
00217
00218
00219
00226 string ScalarCompiler::generateCode (Tree sig)
00227 {
00228 #if 0
00229 fprintf(stderr, "CALL generateCode(");
00230 printSignal(sig, stderr);
00231 fprintf(stderr, ")\n");
00232 #endif
00233
00234 int i;
00235 double r;
00236 Tree c, sel, x, y, z, label, id, ff, largs, type, name, file;
00237
00238
00239
00240 if ( getUserData(sig) ) { return generateXtended(sig); }
00241 else if ( isSigInt(sig, &i) ) { return generateNumber(sig, T(i)); }
00242 else if ( isSigReal(sig, &r) ) { return generateNumber(sig, T(r)); }
00243 else if ( isSigInput(sig, &i) ) { return generateInput (sig, T(i)); }
00244 else if ( isSigOutput(sig, &i, x) ) { return generateOutput (sig, T(i), CS(x));}
00245
00246 else if ( isSigFixDelay(sig, x, y) ) { return generateFixDelay (sig, x, y); }
00247 else if ( isSigPrefix(sig, x, y) ) { return generatePrefix (sig, x, y); }
00248 else if ( isSigIota(sig, x) ) { return generateIota (sig, x); }
00249
00250 else if ( isSigBinOp(sig, &i, x, y) ) { return generateBinOp (sig, i, x, y); }
00251 else if ( isSigFFun(sig, ff, largs) ) { return generateFFun (sig, ff, largs); }
00252 else if ( isSigFConst(sig, type, name, file) ) { return generateFConst(sig, tree2str(file), tree2str(name)); }
00253 else if ( isSigFVar(sig, type, name, file) ) { return generateFVar(sig, tree2str(file), tree2str(name)); }
00254
00255 else if ( isSigTable(sig, id, x, y) ) { return generateTable (sig, x, y); }
00256 else if ( isSigWRTbl(sig, id, x, y, z) ) { return generateWRTbl (sig, x, y, z); }
00257 else if ( isSigRDTbl(sig, x, y) ) { return generateRDTbl (sig, x, y); }
00258
00259 else if ( isSigSelect2(sig, sel, x, y) ) { return generateSelect2 (sig, sel, x, y); }
00260 else if ( isSigSelect3(sig, sel, x, y, z) ) { return generateSelect3 (sig, sel, x, y, z); }
00261
00262 else if ( isSigGen(sig, x) ) { return generateSigGen (sig, x); }
00263
00264 else if ( isProj(sig, &i, x) ) { return generateRecProj (sig, x, i); }
00265
00266 else if ( isSigIntCast(sig, x) ) { return generateIntCast (sig, x); }
00267 else if ( isSigFloatCast(sig, x) ) { return generateFloatCast (sig, x); }
00268
00269 else if ( isSigButton(sig, label) ) { return generateButton (sig, label); }
00270 else if ( isSigCheckbox(sig, label) ) { return generateCheckbox (sig, label); }
00271 else if ( isSigVSlider(sig, label,c,x,y,z) ) { return generateVSlider (sig, label, c,x,y,z); }
00272 else if ( isSigHSlider(sig, label,c,x,y,z) ) { return generateHSlider (sig, label, c,x,y,z); }
00273 else if ( isSigNumEntry(sig, label,c,x,y,z) ) { return generateNumEntry (sig, label, c,x,y,z); }
00274
00275 else if ( isSigVBargraph(sig, label,x,y,z) ) { return generateVBargraph (sig, label, x, y, CS(z)); }
00276 else if ( isSigHBargraph(sig, label,x,y,z) ) { return generateHBargraph (sig, label, x, y, CS(z)); }
00277 else if ( isSigAttach(sig, x, y) ) { CS(y); return generateCacheCode(sig, CS(x)); }
00278
00279 else {
00280 printf("Error in compiling signal, unrecognized signal : ");
00281 print(sig);
00282 printf("\n");
00283 exit(1);
00284 }
00285 return "error in generate code";
00286 }
00287
00288
00289
00290
00291
00292
00293
00294 string ScalarCompiler::generateNumber (Tree sig, const string& exp)
00295 {
00296 string ctype, vname;
00297 Occurences* o = fOccMarkup.retrieve(sig);
00298
00299
00300 if (o->getMaxDelay()>0) {
00301 getTypedNames(getSigType(sig), "Vec", ctype, vname);
00302 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00303 }
00304 return exp;
00305 }
00306
00307
00308
00309
00310
00311
00312 string ScalarCompiler::generateFConst (Tree sig, const string& file, const string& exp)
00313 {
00314 string ctype, vname;
00315 Occurences* o = fOccMarkup.retrieve(sig);
00316
00317 addIncludeFile(file);
00318
00319 if (o->getMaxDelay()>0) {
00320 getTypedNames(getSigType(sig), "Vec", ctype, vname);
00321 generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00322 }
00323 return exp;
00324 }
00325
00326
00327
00328
00329
00330
00331 string ScalarCompiler::generateFVar (Tree sig, const string& file, const string& exp)
00332 {
00333 string ctype, vname;
00334
00335 addIncludeFile(file);
00336 return generateCacheCode(sig, exp);
00337 }
00338
00339
00340
00341
00342
00343
00344 string ScalarCompiler::generateInput (Tree sig, const string& idx)
00345 {
00346 return generateCacheCode(sig, subst("$1input$0[i]", idx, icast()));
00347 }
00348
00349
00350 string ScalarCompiler::generateOutput (Tree sig, const string& idx, const string& arg)
00351 {
00352 string dst = subst("output$0[i]", idx);
00353 fClass->addExecCode(subst("$0 = $2$1;", dst, arg, xcast()));
00354 return dst;
00355 }
00356
00357
00358
00359
00360
00361
00362 string ScalarCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2)
00363 {
00364 return generateCacheCode(sig, subst("($0 $1 $2)", CS(arg1), gBinOpTable[opcode]->fName, CS(arg2)));
00365 }
00366
00367
00368
00369
00370
00371
00372 string ScalarCompiler::generateFFun(Tree sig, Tree ff, Tree largs)
00373 {
00374 addIncludeFile(ffincfile(ff));
00375 addLibrary(fflibfile(ff));
00376
00377 string code = ffname(ff);
00378 code += '(';
00379 string sep = "";
00380 for (int i = 0; i< ffarity(ff); i++) {
00381 code += sep;
00382 code += CS(nth(largs, i));
00383 sep = ", ";
00384 }
00385 code += ')';
00386 return generateCacheCode(sig, code);
00387 }
00388
00389
00390
00391
00392
00393
00394 void ScalarCompiler::getTypedNames(Type t, const string& prefix, string& ctype, string& vname)
00395 {
00396 if (t->nature() == kInt) {
00397 ctype = "int"; vname = subst("i$0", getFreshID(prefix));
00398 } else {
00399 ctype = ifloat(); vname = subst("f$0", getFreshID(prefix));
00400 }
00401 }
00402
00403 string ScalarCompiler::generateCacheCode(Tree sig, const string& exp)
00404 {
00405 string vname, ctype, code;
00406 int sharing = getSharingCount(sig);
00407 Occurences* o = fOccMarkup.retrieve(sig);
00408
00409
00410 if (getCompiledExpression(sig, code)) {
00411 return code;
00412 }
00413
00414
00415 if (o->getMaxDelay()>0) {
00416
00417 getTypedNames(getSigType(sig), "Vec", ctype, vname);
00418 if (sharing>1) {
00419 return generateDelayVec(sig, generateVariableStore(sig,exp), ctype, vname, o->getMaxDelay());
00420 } else {
00421 return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay());
00422 }
00423
00424 } else if (sharing == 1) {
00425
00426 return exp;
00427
00428 } else if (sharing > 1) {
00429
00430 return generateVariableStore(sig, exp);
00431
00432 } else {
00433 cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl;
00434 exit(1);
00435 }
00436
00437 return "Error in generateCacheCode";
00438 }
00439
00440
00441 string ScalarCompiler::generateVariableStore(Tree sig, const string& exp)
00442 {
00443 string vname, ctype;
00444 Type t = getSigType(sig);
00445
00446 switch (t->variability()) {
00447
00448 case kKonst :
00449
00450 getTypedNames(t, "Const", ctype, vname);
00451 fClass->addDeclCode(subst("$0 \t$1;", ctype, vname));
00452 fClass->addInitCode(subst("$0 = $1;", vname, exp));
00453 break;
00454
00455 case kBlock :
00456
00457 getTypedNames(t, "Slow", ctype, vname);
00458 fClass->addFirstPrivateDecl(vname);
00459 fClass->addZone2(subst("$0 \t$1 = $2;", ctype, vname, exp));
00460 break;
00461
00462 case kSamp :
00463
00464 getTypedNames(t, "Temp", ctype, vname);
00465 fClass->addExecCode(subst("$0 $1 = $2;", ctype, vname, exp));
00466 break;
00467 }
00468 return vname;
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 string ScalarCompiler::generateIntCast(Tree sig, Tree x)
00478 {
00479 return generateCacheCode(sig, subst("int($0)", CS(x)));
00480 }
00481
00482 string ScalarCompiler::generateFloatCast (Tree sig, Tree x)
00483 {
00484 return generateCacheCode(sig, subst("$1($0)", CS(x), ifloat()));
00485 }
00486
00487
00488
00489
00490
00491 string ScalarCompiler::generateButton(Tree sig, Tree path)
00492 {
00493 string varname = getFreshID("fbutton");
00494 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00495 fClass->addInitCode(subst("$0 = 0.0;", varname));
00496 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00497 return generateCacheCode(sig, varname);
00498 }
00499
00500 string ScalarCompiler::generateCheckbox(Tree sig, Tree path)
00501 {
00502 string varname = getFreshID("fcheckbox");
00503 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00504 fClass->addInitCode(subst("$0 = 0.0;", varname));
00505 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00506 return generateCacheCode(sig, varname);
00507 }
00508
00509
00510 string ScalarCompiler::generateVSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00511 {
00512 string varname = getFreshID("fslider");
00513 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00514 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
00515 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00516 return generateCacheCode(sig, varname);
00517 }
00518
00519 string ScalarCompiler::generateHSlider(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00520 {
00521 string varname = getFreshID("fslider");
00522 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00523 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
00524 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00525 return generateCacheCode(sig, varname);
00526 }
00527
00528 string ScalarCompiler::generateNumEntry(Tree sig, Tree path, Tree cur, Tree min, Tree max, Tree step)
00529 {
00530 string varname = getFreshID("fentry");
00531 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00532 fClass->addInitCode(subst("$0 = $1;", varname, T(tree2float(cur))));
00533 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00534 return generateCacheCode(sig, varname);
00535 }
00536
00537
00538 string ScalarCompiler::generateVBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00539 {
00540 string varname = getFreshID("fbargraph");
00541 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00542 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00543
00544 Type t = getSigType(sig);
00545 switch (t->variability()) {
00546
00547 case kKonst :
00548 fClass->addInitCode(subst("$0 = $1;", varname, exp));
00549 break;
00550
00551 case kBlock :
00552 fClass->addZone2(subst("$0 = $1;", varname, exp));
00553 break;
00554
00555 case kSamp :
00556 fClass->addExecCode(subst("$0 = $1;", varname, exp));
00557 break;
00558 }
00559
00560
00561 return generateCacheCode(sig, varname);
00562 }
00563
00564
00565 string ScalarCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
00566 {
00567 string varname = getFreshID("fbargraph");
00568 fClass->addDeclCode(subst("$1 \t$0;", varname, xfloat()));
00569 addUIWidget(reverse(tl(path)), uiWidget(hd(path), tree(varname), sig));
00570
00571 Type t = getSigType(sig);
00572 switch (t->variability()) {
00573
00574 case kKonst :
00575 fClass->addInitCode(subst("$0 = $1;", varname, exp));
00576 break;
00577
00578 case kBlock :
00579 fClass->addZone2(subst("$0 = $1;", varname, exp));
00580 break;
00581
00582 case kSamp :
00583 fClass->addExecCode(subst("$0 = $1;", varname, exp));
00584 break;
00585 }
00586
00587
00588 return generateCacheCode(sig, varname);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 string ScalarCompiler::generateSigGen(Tree sig, Tree content)
00605 {
00606 string klassname = getFreshID("SIG");
00607 string signame = getFreshID("sig");
00608
00609 fClass->addSubKlass(signal2klass(klassname, content));
00610 fClass->addInitCode(subst("$0 $1;", klassname, signame));
00611
00612 return signame;
00613 }
00614
00615 string ScalarCompiler::generateStaticSigGen(Tree sig, Tree content)
00616 {
00617 string klassname = getFreshID("SIG");
00618 string signame = getFreshID("sig");
00619
00620 fClass->addSubKlass(signal2klass(klassname, content));
00621 fClass->addStaticInitCode(subst("$0 $1;", klassname, signame));
00622
00623 return signame;
00624 }
00625
00626
00627
00628
00629
00630
00631 string ScalarCompiler::generateTable(Tree sig, Tree tsize, Tree content)
00632 {
00633 string generator(CS(content));
00634 string ctype, vname;
00635 int size;
00636
00637 if (!isSigInt(tsize, &size)) {
00638
00639 cerr << "error in ScalarCompiler::generateTable() : "
00640 << *tsize
00641 << " is not an integer expression "
00642 << endl;
00643 exit(1);
00644 }
00645
00646
00647 Type t = getSigType(content);
00648 if (t->nature() == kInt) {
00649 vname = getFreshID("itbl");
00650 ctype = "int";
00651 } else {
00652 vname = getFreshID("ftbl");
00653 ctype = ifloat();
00654 }
00655
00656
00657 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(size)));
00658
00659
00660 fClass->addInitCode(subst("$0.init(samplingFreq);", generator));
00661
00662 fClass->addInitCode(subst("$0.fill($1,$2);", generator, T(size), vname));
00663
00664
00665 return vname;
00666 }
00667
00668 string ScalarCompiler::generateStaticTable(Tree sig, Tree tsize, Tree content)
00669 {
00670
00671 Tree g;
00672 string cexp;
00673 string ctype, vname;
00674 int size;
00675
00676 assert ( isSigGen(content, g) );
00677 if (!getCompiledExpression(content, cexp)) {
00678 cexp = setCompiledExpression(content, generateStaticSigGen(content, g));
00679 }
00680
00681 if (!isSigInt(tsize, &size)) {
00682
00683 cerr << "error in ScalarCompiler::generateTable() : "
00684 << *tsize
00685 << " is not an integer expression "
00686 << endl;
00687 exit(1);
00688 }
00689
00690
00691 Type t = getSigType(content);
00692 if (t->nature() == kInt) {
00693 vname = getFreshID("itbl");
00694 ctype = "int";
00695 } else {
00696 vname = getFreshID("ftbl");
00697 ctype = ifloat();
00698 }
00699
00700
00701 fClass->addDeclCode(subst("static $0 \t$1[$2];", ctype, vname, T(size)));
00702 fClass->addStaticFields(subst("$0 \tmydsp::$1[$2];", ctype, vname, T(size)));
00703
00704
00705 fClass->addStaticInitCode(subst("$0.init(samplingFreq);", cexp));
00706
00707 fClass->addStaticInitCode(subst("$0.fill($1,$2);", cexp, T(size), vname));
00708
00709
00710 return vname;
00711 }
00712
00713
00714
00715
00716
00717
00718 string ScalarCompiler::generateWRTbl(Tree sig, Tree tbl, Tree idx, Tree data)
00719 {
00720 string tblName(CS(tbl));
00721 fClass->addExecCode(subst("$0[$1] = $2;", tblName, CS(idx), CS(data)));
00722 return tblName;
00723 }
00724
00725
00726
00727
00728
00729
00730 string ScalarCompiler::generateRDTbl(Tree sig, Tree tbl, Tree idx)
00731 {
00732
00733
00734
00735
00736
00737
00738
00739 Tree id, size, content;
00740 if( isSigTable(tbl, id, size, content) ) {
00741 string tblname;
00742 if (!getCompiledExpression(tbl, tblname)) {
00743 tblname = setCompiledExpression(tbl, generateStaticTable(tbl, size, content));
00744 }
00745 return generateCacheCode(sig, subst("$0[$1]", tblname, CS(idx)));
00746 } else {
00747 return generateCacheCode(sig, subst("$0[$1]", CS(tbl), CS(idx)));
00748 }
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00761 string ScalarCompiler::generateRecProj(Tree sig, Tree r, int i)
00762 {
00763 string vname;
00764 Tree var, le;
00765
00766 if ( ! getVectorNameProperty(sig, vname)) {
00767 assert(isRec(r, var, le));
00768 generateRec(r, var, le);
00769 assert(getVectorNameProperty(sig, vname));
00770 }
00771 return subst("$0[0]", vname);
00772 }
00773
00774
00778 void ScalarCompiler::generateRec(Tree sig, Tree var, Tree le)
00779 {
00780 int N = len(le);
00781
00782 vector<bool> used(N);
00783 vector<int> delay(N);
00784 vector<string> vname(N);
00785 vector<string> ctype(N);
00786
00787
00788 for (int i=0; i<N; i++) {
00789 Tree e = sigProj(i,sig);
00790 if (fOccMarkup.retrieve(e)) {
00791
00792 used[i] = true;
00793 getTypedNames(getSigType(e), "Rec", ctype[i], vname[i]);
00794 setVectorNameProperty(e, vname[i]);
00795 delay[i] = fOccMarkup.retrieve(e)->getMaxDelay();
00796 } else {
00797
00798
00799 used[i] = false;
00800 }
00801 }
00802
00803
00804 for (int i=0; i<N; i++) {
00805 if (used[i]) {
00806 generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le,i)));
00807 }
00808 }
00809 }
00810
00811
00812
00813
00814
00815
00816 string ScalarCompiler::generatePrefix (Tree sig, Tree x, Tree e)
00817 {
00818 Type te = getSigType(sig);
00819
00820 string vperm = getFreshID("M");
00821 string vtemp = getFreshID("T");
00822
00823 string type = cType(te);
00824
00825 fClass->addDeclCode(subst("$0 \t$1;", type, vperm));
00826 fClass->addInitCode(subst("$0 = $1;", vperm, CS(x)));
00827
00828 fClass->addExecCode(subst("$0 $1 = $2;", type, vtemp, vperm));
00829 fClass->addExecCode(subst("$0 = $1;", vperm, CS(e)));
00830 return vtemp;
00831 }
00832
00833
00834
00835
00836
00837 static bool isPowerOf2(int n)
00838 {
00839 return !(n & (n - 1));
00840 }
00841
00842 string ScalarCompiler::generateIota (Tree sig, Tree n)
00843 {
00844 int size;
00845 if (!isSigInt(n, &size)) { fprintf(stderr, "error in generateIota\n"); exit(1); }
00846
00847 string vperm = getFreshID("iota");
00848
00849 fClass->addDeclCode(subst("int \t$0;", vperm));
00850 fClass->addInitCode(subst("$0 = 0;", vperm));
00851
00852 if (isPowerOf2(size)) {
00853 fClass->addExecCode(subst("$0 = ($0+1)&$1;", vperm, T(size-1)));
00854 } else {
00855 fClass->addExecCode(subst("if (++$0 == $1) $0=0;", vperm, T(size)));
00856 }
00857 return vperm;
00858 }
00859
00860
00861
00862
00863
00864
00869 string ScalarCompiler::generateSelect2 (Tree sig, Tree sel, Tree s1, Tree s2)
00870 {
00871 return generateCacheCode(sig, subst( "(($0)?$1:$2)", CS(sel), CS(s2), CS(s1) ) );
00872 }
00873
00874
00880 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3)
00881 {
00882 return generateCacheCode(sig, subst( "(($0==0)? $1 : (($0==1)?$2:$3) )", CS(sel), CS(s1), CS(s2), CS(s3) ) );
00883 }
00884
00885 #if 0
00886 string ScalarCompiler::generateSelect3 (Tree sig, Tree sel, Tree s1, Tree s2, Tree s3)
00887 {
00888 Type t = getSigType(sig);
00889 Type t1 = getSigType(s1);
00890 Type t2 = getSigType(s2);
00891 Type t3 = getSigType(s3);
00892 Type w = min(t1,min(t2,t3));
00893
00894 string type = cType(t);
00895 string var = getFreshID("S");
00896
00897 switch (w->variability())
00898 {
00899 case kKonst :
00900 fClass->addDeclCode(subst("$0 \t$1[3];", type, var));
00901 break;
00902 case kBlock :
00903
00904
00905 fClass->addSharedDecl(var);
00906 fClass->addZone1(subst("$0 \t$1[3];", type, var));
00907 break;
00908 case kSamp :
00909 fClass->addExecCode(subst("$0 \t$1[3];", type, var));
00910 break;
00911 }
00912
00913 switch (t1->variability())
00914 {
00915 case kKonst :
00916 fClass->addInitCode(subst("$0[0] = $1;", var, CS(s1)));
00917 break;
00918 case kBlock :
00919 fClass->addZone2b(subst("$0[0] = $1;", var, CS(s1)));
00920 break;
00921 case kSamp :
00922 fClass->addExecCode(subst("$0[0] = $1;", var, CS(s1)));
00923 break;
00924 }
00925
00926 switch (t2->variability())
00927 {
00928 case kKonst :
00929 fClass->addInitCode(subst("$0[1] = $1;", var, CS(s2)));
00930 break;
00931 case kBlock :
00932 fClass->addZone2b(subst("$0[1] = $1;", var, CS(s2)));
00933 break;
00934 case kSamp :
00935 fClass->addExecCode(subst("$0[1] = $1;", var, CS(s2)));
00936 break;
00937 }
00938
00939 switch (t3->variability())
00940 {
00941 case kKonst :
00942 fClass->addInitCode(subst("$0[2] = $1;", var, CS(s3)));
00943 break;
00944 case kBlock :
00945 fClass->addZone2b(subst("$0[2] = $1;", var, CS(s3)));
00946 break;
00947 case kSamp :
00948 fClass->addExecCode(subst("$0[2] = $1;", var, CS(s3)));
00949 break;
00950 }
00951
00952 return generateCacheCode(sig, subst("$0[$1]", var, CS(sel)));
00953 }
00954 #endif
00955
00960 string ScalarCompiler::generateXtended (Tree sig)
00961 {
00962 xtended* p = (xtended*) getUserData(sig);
00963 vector<string> args;
00964 vector<Type> types;
00965
00966 for (int i=0; i<sig->arity(); i++) {
00967 args.push_back(CS(sig->branch(i)));
00968 types.push_back(getSigType(sig->branch(i)));
00969 }
00970
00971 if (p->needCache()) {
00972 return generateCacheCode(sig, p->generateCode(fClass, args, types));
00973 } else {
00974 return p->generateCode(fClass, args, types);
00975 }
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00994 void ScalarCompiler::setVectorNameProperty(Tree sig, const string& vecname)
00995 {
00996 fVectorProperty.set(sig, vecname);
00997 }
00998
00999
01008 bool ScalarCompiler::getVectorNameProperty(Tree sig, string& vecname)
01009 {
01010 return fVectorProperty.get(sig, vecname);
01011 }
01012
01013
01018 int ScalarCompiler::pow2limit(int x)
01019 {
01020 int n = 2;
01021 while (n < x) { n = 2*n; }
01022 return n;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01051 string ScalarCompiler::generateFixDelay (Tree sig, Tree exp, Tree delay)
01052 {
01053 int mxd, d;
01054 string vecname;
01055
01056
01057
01058
01059
01060 CS(exp);
01061
01062 mxd = fOccMarkup.retrieve(exp)->getMaxDelay();
01063
01064 if (! getVectorNameProperty(exp, vecname)) {
01065 cerr << "No vector name for : " << ppsig(exp) << endl;
01066 assert(0);
01067 }
01068
01069 if (mxd == 0) {
01070
01071 return vecname;
01072
01073 } else if (mxd < gMaxCopyDelay) {
01074 if (isSigInt(delay, &d)) {
01075 return subst("$0[$1]", vecname, CS(delay));
01076 } else {
01077 return generateCacheCode(sig, subst("$0[$1]", vecname, CS(delay)));
01078 }
01079
01080 } else {
01081
01082
01083 int N = pow2limit( mxd+1 );
01084 return generateCacheCode(sig, subst("$0[(IOTA-$1)&$2]", vecname, CS(delay), T(N-1)));
01085 }
01086 }
01087
01088
01094 string ScalarCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01095 {
01096 string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd);
01097 if (getSigType(sig)->variability() < kSamp) {
01098 return exp;
01099 } else {
01100 return s;
01101 }
01102 }
01103
01108 string ScalarCompiler::generateDelayVecNoTemp(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
01109 {
01110 assert(mxd > 0);
01111
01112
01113
01114 if (mxd < gMaxCopyDelay) {
01115
01116
01117 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1)));
01118 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1)));
01119 fClass->addExecCode(subst("$0[0] = $1;", vname, exp));
01120
01121
01122 if (mxd == 1) {
01123 fClass->addPostCode(subst("$0[1] = $0[0];", vname));
01124 } else if (mxd == 2) {
01125
01126 fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname));
01127 } else {
01128 fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname));
01129 }
01130 setVectorNameProperty(sig, vname);
01131 return subst("$0[0]", vname);
01132
01133 } else {
01134
01135
01136 int N = pow2limit(mxd+1);
01137
01138
01139 ensureIotaCode();
01140
01141
01142 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N)));
01143 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N)));
01144
01145
01146 fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp));
01147 setVectorNameProperty(sig, vname);
01148 return subst("$0[IOTA&$1]", vname, T(N-1));
01149 }
01150 }
01151
01156 void ScalarCompiler::generateDelayLine(const string& ctype, const string& vname, int mxd, const string& exp)
01157 {
01158
01159 if (mxd == 0) {
01160
01161
01162 fClass->addExecCode(subst("$0 \t$1 = $2;", ctype, vname, exp));
01163
01164
01165 } else if (mxd < gMaxCopyDelay) {
01166
01167
01168 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(mxd+1)));
01169 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(mxd+1)));
01170 fClass->addExecCode(subst("$0[0] = $1;", vname, exp));
01171
01172
01173 if (mxd == 1) {
01174 fClass->addPostCode(subst("$0[1] = $0[0];", vname));
01175 } else if (mxd == 2) {
01176 fClass->addPostCode(subst("$0[2] = $0[1]; $0[1] = $0[0];", vname));
01177 } else {
01178 fClass->addPostCode(subst("for (int i=$0; i>0; i--) $1[i] = $1[i-1];", T(mxd), vname));
01179 }
01180
01181 } else {
01182
01183
01184 int N = pow2limit(mxd+1);
01185
01186
01187 ensureIotaCode();
01188
01189
01190 fClass->addDeclCode(subst("$0 \t$1[$2];", ctype, vname, T(N)));
01191 fClass->addInitCode(subst("for (int i=0; i<$1; i++) $0[i] = 0;", vname, T(N)));
01192
01193
01194 fClass->addExecCode(subst("$0[IOTA&$1] = $2;", vname, T(N-1), exp));
01195 }
01196 }
01197
01202 void ScalarCompiler::ensureIotaCode()
01203 {
01204 if (!fHasIota) {
01205 fHasIota = true;
01206 fClass->addDeclCode("int \tIOTA;");
01207 fClass->addInitCode("IOTA = 0;");
01208 fClass->addPostCode("IOTA = IOTA+1;");
01209 }
01210 }