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