Example #1
0
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);
    }
}
Example #2
0
/**
 * 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;
}
Example #3
0
/**
 * 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;
}
Example #4
0
/**
 * Generate code for the delay mecchanism. The generated code depend of the
 * maximum delay attached to exp and the "less temporaries" switch
 */
string DocCompiler::generateDelayVec(Tree sig, const string& exp, const string& ctype, const string& vname, int mxd)
{
	string s = generateDelayVecNoTemp(sig, exp, ctype, vname, mxd);
	if (getCertifiedSigType(sig)->variability() < kSamp) {
        return exp;
	} else {
		return s;
	}
}
Example #5
0
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";
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #8
0
/**
 * Compile a signal
 * @param sig the signal expression to compile.
 * @return the C code translation of sig as a string
 */
string  VectorCompiler::CS (Tree sig)
{
    string      code;
    //cerr << "ENTER VectorCompiler::CS : "<< ppsig(sig) << endl;
    if (!getCompiledExpression(sig, code)) {
        code = generateCode(sig);
		//cerr << "CS : " << code << " for " << ppsig(sig) << endl;
        setCompiledExpression(sig, code);
    } else {
        // we require an already compiled expression
        // therefore we must update the dependencies of
        // the current loop
        int     i;
        Tree	x, d, r;
        Loop*   ls;
        Loop*   tl = fClass->topLoop();

        if (fClass->getLoopProperty(sig,ls)) {
            // sig has a loop property
            //cerr << "CASE SH : fBackwardLoopDependencies.insert : " << tl << " --depend(A)son--> " << ls << endl;
			tl->fBackwardLoopDependencies.insert(ls);

        } else if (isSigFixDelay(sig, x, d) && fClass->getLoopProperty(x,ls)) {
            //cerr << "CASE DL : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl;
            tl->fBackwardLoopDependencies.insert(ls);

        } else if (isSigFixDelay(sig, x, d) && isProj(x, &i, r) && fClass->getLoopProperty(r,ls)) {
            //cerr << "CASE DR : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl;
            tl->fBackwardLoopDependencies.insert(ls);

        } else if (isProj(sig, &i, r) && fClass->getLoopProperty(r,ls)) {
            //cerr << "CASE R* : fBackwardLoopDependencies.insert : " << tl << " --depend(B)son--> " << ls << endl;
            tl->fBackwardLoopDependencies.insert(ls);

        } else {
            if (isProj(sig, &i, r)) {
                //cerr << "SYMBOL RECURSIF EN COURS ??? " << *r << endl;
            } else if (getCertifiedSigType(sig)->variability()<kSamp) {
                //cerr << "SLOW EXPRESSION " << endl;
            } else {
                //cerr << "Expression absorbée" << *sig << endl;
            }

        }
    }
    //cerr << "EXIT VectorCompiler::CS : "<< ppsig(sig) << "---code---> " << code << endl;
	return code;
}
Example #9
0
string DocCompiler::generateHBargraph(Tree sig, Tree path, Tree min, Tree max, const string& exp)
{
	string varname = getFreshID("{u_g}");

	Type t = getCertifiedSigType(sig);
	switch (t->variability()) {

		case kKonst :
			break;

		case kBlock :
			break;

		case kSamp :
			break;
	}
    return generateCacheCode(sig, varname);
}
Example #10
0
/**
 * 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));
    }
  }
}
Example #11
0
/**
 * retrieve the type annotation of sig
 * @param sig the signal we want to know the type
 */
string DocCompiler::generateXtended 	(Tree sig, int priority)
{
	xtended* p = (xtended*) getUserData(sig);
	vector<string> args;
	vector<Type> types;

	for (int i=0; i<sig->arity(); i++) {
		args.push_back(CS(sig->branch(i), 0));
		types.push_back(getCertifiedSigType(sig->branch(i)));
	}

	if (p->needCache()) {
		//cerr << "!! generateXtended : <needCache> : calls generateCacheCode(sig, p->generateLateq(fLateq, args, types))" << endl;
		return generateCacheCode(sig, p->generateLateq(fLateq, args, types));
	} else {
		//cerr << "!! generateXtended : <do not needCache> : calls p->generateLateq(fLateq, args, types)" << endl;
		return p->generateLateq(fLateq, args, types);
	}
}
Example #12
0
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+"}";
}
Example #13
0
//------------------------------------------------------------------------------
// 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;
}
Example #14
0
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 "";
  }
}
Example #15
0
/**
 * 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;
}
Example #16
0
/**
 * 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;
            }
        }
    }
}
Example #17
0
string DocCompiler::generateBinOp(Tree sig, int opcode, Tree arg1, Tree arg2, int priority)
{
  string s;
  int thisPriority = gBinOpLateqTable[opcode]->fPriority;

  /* Priority parenthesis handling. */
  string lpar = "";
  string rpar = "";

  if((thisPriority < priority) || ((thisPriority == priority) && !associative(opcode)))
  {
    // (a+b)*c or (a/b)/c need parenthesis
    lpar = " \\left(";
    rpar = "\\right) ";
  }

  Type t1 = getCertifiedSigType(arg1);
  Type t2 = getCertifiedSigType(arg2);
  bool intOpDetected = false;

  if((t1->nature() == kInt) && (t2->nature() == kInt))
  {
    intOpDetected = true;
  }

  string op;

  if(!intOpDetected)
  {
    op = gBinOpLateqTable[opcode]->fName;
  }
  else
  {
    switch(opcode)
    {
    case kAdd:
      op = "\\oplus";
      gDocNoticeFlagMap["intplus"] = true;
      break;
    case kSub:
      op = "\\ominus";
      gDocNoticeFlagMap["intminus"] = true;
      break;
    case kMul:
      op = "\\odot";
      gDocNoticeFlagMap["intmult"] = true;
      break;
    case kDiv:
      op = "\\oslash";
      gDocNoticeFlagMap["intdiv"] = true;
      gDocNoticeFlagMap["intcast"] = true; // "$normalize(int(i/j))$" in the notice.
      break;
    default:
      op = gBinOpLateqTable[opcode]->fName;
      break;
    }
  }

  /* LaTeX frac{}{} handling VS general case. */
  if((opcode == kDiv) && (!intOpDetected))
  {
    s = subst("$0\\frac{$1}{$2}$3", lpar, CS(arg1, 0), CS(arg2, 0), rpar);
  }
  else
  {
    s = subst("$0$1 $2 $3$4", lpar, CS(arg1, thisPriority), op, CS(arg2, thisPriority), rpar);
  }

// if (opcode == kMul) {
// gDocNoticeFlagMap["cdot"] = true;
// }

  return generateCacheCode(sig, s);
}