string DocCompiler::generateCacheCode(Tree sig, const string& exp) { // cerr << "!! entering generateCacheCode with sig=\"" << ppsig(sig) << "\"" << endl; string vname, ctype, code, vectorname; int sharing = getSharingCount(sig); Occurences* o = fOccMarkup.retrieve(sig); // check reentrance if(getCompiledExpression(sig, code)) { // cerr << "!! generateCacheCode called a true getCompiledExpression" << endl; return code; } // check for expression occuring in delays if(o->getMaxDelay() > 0) { if(getVectorNameProperty(sig, vectorname)) { return exp; } getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); gDocNoticeFlagMap["recursigs"] = true; // cerr << "- r : generateCacheCode : vame=\"" << vname << "\", for sig=\"" << ppsig(sig) << "\"" << endl; if(sharing > 1) { // cerr << " generateCacheCode calls generateDelayVec(generateVariableStore) on vame=\"" << vname << "\"" << endl; return generateDelayVec(sig, generateVariableStore(sig, exp), ctype, vname, o->getMaxDelay()); } else { // cerr << " generateCacheCode calls generateDelayVec(exp) on vame=\"" << vname << "\"" << endl; return generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); } } else if(sharing == 1 || getVectorNameProperty(sig, vectorname) || isVerySimpleFormula(sig)) { // cerr << "! generateCacheCode : sharing == 1 : return \"" << exp << "\"" << endl; return exp; } else if(sharing > 1) { // cerr << "! generateCacheCode : sharing > 1 : return \"" << exp << "\"" << endl; return generateVariableStore(sig, exp); } else { cerr << "Error in sharing count (" << sharing << ") for " << *sig << endl; exit(1); } return "Error in generateCacheCode"; }
//------------------------------------------------------------------------------ // Create a specific property key for the sharing count of subtrees of t //------------------------------------------------------------------------------ void ScalarCompiler::sharingAnnotation(int vctxt, Tree sig) { Tree c, x, y, z; //cerr << "START sharing annotation of " << *sig << endl; int count = getSharingCount(sig); if (count > 0) { // it is not our first visit setSharingCount(sig, count+1); } else { // it is our first visit, int v = getCertifiedSigType(sig)->variability(); // check "time sharing" cases if (v < vctxt) { setSharingCount(sig, 2); // time sharing occurence : slower expression in faster context } else { setSharingCount(sig, 1); // regular occurence } if (isSigSelect3(sig,c,y,x,z)) { // make a special case for select3 implemented with real if // because the c expression will be used twice in the C++ // translation sharingAnnotation(v, c); sharingAnnotation(v, c); sharingAnnotation(v, x); sharingAnnotation(v, y); sharingAnnotation(v, z); } else { // Annotate the sub signals vector<Tree> subsig; int n = getSubSignals(sig, subsig); if (n>0 && ! isSigGen(sig)) { for (int i=0; i<n; i++) sharingAnnotation(v, subsig[i]); } } } //cerr << "END sharing annotation of " << *sig << endl; }
/** * Test if a signal need to be compiled in a separate loop. * @param sig the signal expression to test. * @return true if a separate loop is needed */ bool VectorCompiler::needSeparateLoop(Tree sig) { Occurences* o = fOccMarkup.retrieve(sig); Type t = getCertifiedSigType(sig); int c = getSharingCount(sig); bool b; int i; Tree x,y; if (o->getMaxDelay()>0) { //cerr << "DLY "; // delayed expressions require a separate loop b = true; } else if (verySimple(sig) || t->variability()<kSamp) { b = false; // non sample computation never require a loop } else if (isSigFixDelay(sig, x, y)) { b = false; // } else if (isProj(sig, &i ,x)) { //cerr << "REC "; // recursive expressions require a separate loop b = true; } else if (c > 1) { //cerr << "SHA(" << c << ") "; // expressions used several times required a separate loop b = true; } else { // sample expressions that are not recursive, not delayed // and not shared, doesn't require a separate loop. b = false; } /* if (b) { cerr << "Separate Loop for " << ppsig(sig) << endl; } else { cerr << "Same Loop for " << ppsig(sig) << endl; }*/ return b; }
/** * Generate cache code for a signal if needed * @param sig the signal expression. * @param exp the corresponding C code. * @return the cached C code */ string VectorCompiler::generateCacheCode(Tree sig, const string& exp) { string vname, ctype; int sharing = getSharingCount(sig); Type t = getCertifiedSigType(sig); Occurences* o = fOccMarkup.retrieve(sig); int d = o->getMaxDelay(); if (t->variability() < kSamp) { if (d==0) { // non-sample, not delayed : same as scalar cache return ScalarCompiler::generateCacheCode(sig,exp); } else { // it is a non-sample expressions but used delayed // we need a delay line getTypedNames(getCertifiedSigType(sig), "Vec", ctype, vname); if ((sharing > 1) && !verySimple(sig)) { // first cache this expression because it // it is shared and complex string cachedexp = generateVariableStore(sig, exp); generateDelayLine(ctype, vname, d, cachedexp); setVectorNameProperty(sig, vname); return cachedexp; } else { // no need to cache this expression because // it is either not shared or very simple generateDelayLine(ctype, vname, d, exp); setVectorNameProperty(sig, vname); return exp; } } } else { // sample-rate signal if (d > 0) { // used delayed : we need a delay line getTypedNames(getCertifiedSigType(sig), "Yec", ctype, vname); generateDelayLine(ctype, vname, d, exp); setVectorNameProperty(sig, vname); if (verySimple(sig)) { return exp; } else { if (d < gMaxCopyDelay) { return subst("$0[i]", vname); } else { // we use a ring buffer string mask = T(pow2limit(d + gVecSize)-1); return subst("$0[($0_idx+i) & $1]", vname, mask); } } } else { // not delayed if ( sharing > 1 && ! verySimple(sig) ) { // shared and not simple : we need a vector // cerr << "ZEC : " << ppsig(sig) << endl; getTypedNames(getCertifiedSigType(sig), "Zec", ctype, vname); generateDelayLine(ctype, vname, d, exp); setVectorNameProperty(sig, vname); return subst("$0[i]", vname); } else { // not shared or simple : no cache needed return exp; } } } }