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