/** * Generate the equation of a write table, which content is time dependent. * It is basically a signal of vectors. */ string DocCompiler::generateDocWriteTbl(Tree /*tbl*/, Tree size, Tree isig, Tree widx, Tree wsig) { string vname, ctype; string init = CS(isig, 0); int n; if(!isSigInt(size, &n)) { cerr << "error in DocCompiler::generateDocWriteTbl() : " << *size << " is not an integer expression and can't be used as a table size' " << endl; } // allocate a name w_i for the table getTypedNames(getCertifiedSigType(isig), "w", ctype, vname); // add a comment on tables in the notice gDocNoticeFlagMap["tablesigs"] = true; // describe the table equation string ltqRWTableDef; ltqRWTableDef += subst("$0(t)[i] = \n", vname); ltqRWTableDef += "\\left\\{\\begin{array}{ll}\n"; ltqRWTableDef += subst("$0 & \\mbox{if \\,} t < 0 \\mbox{\\, and \\,} i \\in [0,$1] \\\\\n", replaceTimeBy(init, 'i'), T(n - 1)); ltqRWTableDef += subst("$0 & \\mbox{if \\,} i = $1 \\\\\n", CS(wsig, 0), CS(widx, 0)); ltqRWTableDef += subst("$0(t\\!-\\!1)[i] & \\mbox{otherwise} \\\\\n", vname); ltqRWTableDef += "\\end{array}\\right."; // add the table equation fLateq->addRWTblSigFormula(ltqRWTableDef); // w(t) = initsig(t) // note that the name of the table can never be used outside an sigDocTableAccess return vname; }
/** * Generate the equation of a constant table (its content is time constant). * Returns the name of the table */ string DocCompiler::generateDocConstantTbl(Tree /*tbl*/, Tree size, Tree isig) { string vname, ctype; string init = CS(isig, 0); int n; if(!isSigInt(size, &n)) { cerr << "error in DocCompiler::generateDocConstantTbl() : " << *size << " is not an integer expression and can't be used as a table size' " << endl; } // allocate a name v_i for the table getTypedNames(getCertifiedSigType(isig), "v", ctype, vname); // add a comment on tables in the notice gDocNoticeFlagMap["tablesigs"] = true; // add equation v[t] = isig(t) fLateq->addRDTblSigFormula(subst("$0[t] = $1 \\condition{when $$t \\in [0,$2]$$} ", vname, init, T(n - 1))); // note that the name of the table can never be used outside an sigDocTableAccess return vname; }
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"; }
string DocCompiler::generateVariableStore(Tree sig, const string& exp) { string vname, ctype; Type t = getCertifiedSigType(sig); switch(t->variability()) { case kKonst: getTypedNames(t, "k", ctype, vname); ///< "k" for constants. fLateq->addConstSigFormula(subst("$0 = $1", vname, exp)); gDocNoticeFlagMap["constsigs"] = true; return vname; case kBlock: getTypedNames(t, "p", ctype, vname); ///< "p" for "parameter". fLateq->addParamSigFormula(subst("$0(t) = $1", vname, exp)); gDocNoticeFlagMap["paramsigs"] = true; setVectorNameProperty(sig, vname); return subst("$0(t)", vname); case kSamp: if(getVectorNameProperty(sig, vname)) { return subst("$0(t)", vname); } else { getTypedNames(t, "s", ctype, vname); // cerr << "- generateVariableStore : \"" << subst("$0(t) = $1", vname, exp) << "\"" << endl; fLateq->addStoreSigFormula(subst("$0(t) = $1", vname, exp)); gDocNoticeFlagMap["storedsigs"] = true; setVectorNameProperty(sig, vname); return subst("$0(t)", vname); } default: assert(0); return ""; } }
string VectorCompiler::generateVariableStore(Tree sig, const string& exp) { Type t = getCertifiedSigType(sig); if (getCertifiedSigType(sig)->variability() == kSamp) { string vname, ctype; getTypedNames(t, "Vector", ctype, vname); vectorLoop(ctype, vname, exp); return subst("$0[i]", vname); } else { return ScalarCompiler::generateVariableStore(sig, exp); } }
string DocCompiler::generateFVar (Tree sig, const string& file, const string& exp) { string ctype, vname; Occurences* o = fOccMarkup.retrieve(sig); if (o->getMaxDelay()>0) { getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); gGlobal->gDocNoticeFlagMap["recursigs"] = true; //cerr << "- r : generateFVar : \"" << vname << "\"" << endl; setVectorNameProperty(sig, vname); generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); } return generateCacheCode(sig, exp); }
string DocCompiler::generateNumber (Tree sig, const string& exp) { string ctype, vname; Occurences* o = fOccMarkup.retrieve(sig); // check for number occuring in delays if (o->getMaxDelay()>0) { getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); gGlobal->gDocNoticeFlagMap["recursigs"] = true; //cerr << "- r : generateNumber : \"" << vname << "\"" << endl; generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); } return exp; }
/** * Generate code for a group of mutually recursive definitions */ void DocCompiler::generateRec(Tree sig, Tree var, Tree le, int priority) { int N = len(le); vector<bool> used(N); vector<int> delay(N); vector<string> vname(N); vector<string> ctype(N); // prepare each element of a recursive definition for(int i = 0; i < N; i++) { Tree e = sigProj(i, sig); // recreate each recursive definition if(fOccMarkup.retrieve(e)) { // this projection is used used[i] = true; // cerr << "generateRec : used[" << i << "] = true" << endl; getTypedNames(getCertifiedSigType(e), "r", ctype[i], vname[i]); gDocNoticeFlagMap["recursigs"] = true; // cerr << "- r : generateRec setVectorNameProperty : \"" << vname[i] << "\"" << endl; setVectorNameProperty(e, vname[i]); delay[i] = fOccMarkup.retrieve(e)->getMaxDelay(); } else { // this projection is not used therefore // we should not generate code for it used[i] = false; // cerr << "generateRec : used[" << i << "] = false" << endl; } } // generate delayline for each element of a recursive definition for(int i = 0; i < N; i++) { if(used[i]) { generateDelayLine(ctype[i], vname[i], delay[i], CS(nth(le, i), priority)); } } }
string DocCompiler::generateFConst (Tree sig, const string& file, const string& exp) { string ctype, vname; Occurences* o = fOccMarkup.retrieve(sig); if (o->getMaxDelay()>0) { getTypedNames(getCertifiedSigType(sig), "r", ctype, vname); gGlobal->gDocNoticeFlagMap["recursigs"] = true; //cerr << "- r : generateFConst : \"" << vname << "\"" << endl; generateDelayVec(sig, exp, ctype, vname, o->getMaxDelay()); } if (exp == "fSamplingFreq") { //gGlobal->gDocNoticeFlagMap["fsamp"] = true; return "f_S"; } return "\\mathrm{"+exp+"}"; }
/** * 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; } } } }