From 895b3792ac9c07b1b96e1b3b8b7410c1e4b06db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Letz?= Date: Mon, 24 Feb 2025 10:44:02 +0100 Subject: [PATCH] Different DS counters have to be allocated for each DS block, correct SR adaptation in propagate. --- compiler/generator/instructions_compiler.cpp | 77 +++++++++++--------- compiler/generator/instructions_compiler.hh | 5 +- compiler/propagate/propagate.cpp | 23 ++++-- compiler/signals/signals.cpp | 4 +- 4 files changed, 64 insertions(+), 45 deletions(-) diff --git a/compiler/generator/instructions_compiler.cpp b/compiler/generator/instructions_compiler.cpp index ecfe0ea707..754b0ce358 100644 --- a/compiler/generator/instructions_compiler.cpp +++ b/compiler/generator/instructions_compiler.cpp @@ -444,9 +444,9 @@ bool InstructionsCompiler::getVectorNameProperty(Tree sig, string& vname) * @return the vector name associated with sig */ -std::string InstructionsCompiler::ensureVectorNameProperty(const std::string& altname, Tree sig) +string InstructionsCompiler::ensureVectorNameProperty(const string& altname, Tree sig) { - std::string vecname; + string vecname; if (!getVectorNameProperty(sig, vecname)) { vecname = altname; setVectorNameProperty(sig, vecname); @@ -1230,9 +1230,9 @@ void InstructionsCompiler::getTypedNames(::Type t, const string& prefix, BasicTy void InstructionsCompiler::getTypedNames(::Type t, const string& prefix, Typed::VarType& ctype, string& vname) { - std::string typedescr = "VC"; - typedescr[0] = "KB?S"[t->variability()]; - typedescr[1] = "CI?E"[t->computability()]; + string typedescr = "VC"; + typedescr[0] = "KB?S"[t->variability()]; + typedescr[1] = "CI?E"[t->computability()]; if (t->nature() == kInt) { ctype = Typed::kInt32; vname = subst("i$0$1", gGlobal->getFreshID(prefix), typedescr.c_str()); @@ -1245,9 +1245,9 @@ void InstructionsCompiler::getTypedNames(::Type t, const string& prefix, Typed:: void InstructionsCompiler::getTypedNames(::Type t, const string& prefix, BasicTyped*& ctype, string& vname) { - std::string typedescr = "VC"; - typedescr[0] = "KB?S"[t->variability()]; - typedescr[1] = "CI?E"[t->computability()]; + string typedescr = "VC"; + typedescr[0] = "KB?S"[t->variability()]; + typedescr[1] = "CI?E"[t->computability()]; if (t->nature() == kInt) { ctype = IB::genBasicTyped(Typed::kInt32); vname = subst("i$0$1", gGlobal->getFreshID(prefix), typedescr.c_str()); @@ -2438,7 +2438,7 @@ string InstructionsCompiler::declareRetrieveIotaName(Tree clock) return iotaname; } - std::string newiotaname = gGlobal->getFreshID("IOTA"); + string newiotaname = gGlobal->getFreshID("IOTA"); fIotaProperty.set(clock, newiotaname); pushDeclare(IB::genDecStructVar(newiotaname, IB::genInt32Typed())); @@ -2450,6 +2450,25 @@ string InstructionsCompiler::declareRetrieveIotaName(Tree clock) return newiotaname; } +string InstructionsCompiler::declareRetrieveDSName(Tree clock) +{ + // std::cerr << "declareRetrieveIotaName(" << *clock << ")" << endl; + if (string dsname; fDSProperty.get(clock, dsname)) { + return dsname; + } + + string newdsname = gGlobal->getFreshID("DSCounter"); + fDSProperty.set(clock, newdsname); + + pushDeclare(IB::genDecStructVar(newdsname, IB::genInt32Typed())); + pushClearMethod(IB::genStoreStructVar(newdsname, IB::genInt32NumInst(0))); + + FIRIndex value = FIRIndex(IB::genLoadStructVar(newdsname)) + 1; + pushPostComputeDSPMethod(IB::genStoreStructVar(newdsname, value)); + + return newdsname; +} + ValueInst* InstructionsCompiler::generateDelayAccess(Tree sig, Tree exp, ValueInst* delayidx) { Typed::VarType ctype; @@ -2499,7 +2518,7 @@ ValueInst* InstructionsCompiler::generateDelayAccess(Tree sig, Tree exp, ValueIn int N = pow2limit(mxd + 1); Tree clock; faustassert(hasClock(exp, clock)); - std::string iotaname = declareRetrieveIotaName(clock); + string iotaname = declareRetrieveIotaName(clock); // result = subst("$0[($1-$2)&$3]", vecname, iotaname, delayidx, // T(N - 1)); // idx can't be cashed as it depends of loop variable ii @@ -2603,8 +2622,8 @@ ValueInst* InstructionsCompiler::generateDelayVecNoTemp(Tree sig, ValueInst* exp faustassert(mxd > 0); // We make sure to use the vector name associated with signal, or we provide one - std::string vecname = ensureVectorNameProperty(pname, sig); - bool mono = isSigSimpleRec(sig); + string vecname = ensureVectorNameProperty(pname, sig); + bool mono = isSigSimpleRec(sig); // bool odocc = fOccMarkup->retrieve(sig)->hasOutDelayOccurrences(); ValueInst* ccs = getConditionCode(sig); // DelayType dt = analyzeDelayType(sig); @@ -2705,8 +2724,8 @@ StatementInst* InstructionsCompiler::generateCopyArray(const string& vname_to, } // for (int j = 0; j < size; j++) { v1[j+1] = v2[j]; } -StatementInst* InstructionsCompiler::generateMove1Array(const std::string& v1, - const std::string& v2, int size) +StatementInst* InstructionsCompiler::generateMove1Array(const string& v1, const string& v2, + int size) { string index = gGlobal->getFreshID("j"); @@ -2725,8 +2744,8 @@ StatementInst* InstructionsCompiler::generateMove1Array(const std::string& v1, } // for (int j = 0; j < size; j++) { v1[j] = v2[j+1]; } -StatementInst* InstructionsCompiler::generateMove2Array(const std::string& v1, - const std::string& v2, int size) +StatementInst* InstructionsCompiler::generateMove2Array(const string& v1, const string& v2, + int size) { string index = gGlobal->getFreshID("j"); @@ -2744,9 +2763,9 @@ StatementInst* InstructionsCompiler::generateMove2Array(const std::string& v1, return loop; } -ValueInst* InstructionsCompiler::generateDelayLine(Tree sig, BasicTyped* ctype, - const std::string& vname, int mxd, int count, - bool mono, ValueInst* exp, ValueInst* ccs) +ValueInst* InstructionsCompiler::generateDelayLine(Tree sig, BasicTyped* ctype, const string& vname, + int mxd, int count, bool mono, ValueInst* exp, + ValueInst* ccs) { DelayType dt = analyzeDelayType(sig); switch (dt) { @@ -2909,7 +2928,7 @@ ValueInst* InstructionsCompiler::generateDelayLine(Tree sig, BasicTyped* ctype, case DelayType::kSelectRingDelay: Tree clock; faustassert(hasClock(sig, clock)); - std::string iotaname = declareRetrieveIotaName(clock); + string iotaname = declareRetrieveIotaName(clock); // std::cerr << "Use of ring buffer " << vname << " with sig = " << sig << std::endl; // generate code for a long delay : we use a ring buffer of size N = 2**x > mxd @@ -3350,8 +3369,8 @@ ValueInst* InstructionsCompiler::generateFIR(Tree sig, const tvec& coefs) faustassert(false); } - // std::string csize = T(int(coefs.size() - 1)); - // std::string ctabledecl = subst("const $0 \t$1[$2] = $3;", ctype, ctable, csize, + // string csize = T(int(coefs.size() - 1)); + // string ctabledecl = subst("const $0 \t$1[$2] = $3;", ctype, ctable, csize, // coefInit); // Defined as a global static @@ -3512,7 +3531,7 @@ ValueInst* InstructionsCompiler::generatePermVar(Tree sig, Tree x) // compute a perm var name getTypedNames(getCertifiedSigType(sig), "PermVar", ctype, name); // assign it to sig unless it has already a name - std::string pvname = ensureVectorNameProperty(name, sig); + string pvname = ensureVectorNameProperty(name, sig); // declare the perm var as a class field pushDeclare(IB::genLabelInst("// Perm Var")); pushDeclare(IB::genDecStructVar(pvname, ctype)); @@ -3648,16 +3667,6 @@ ValueInst* InstructionsCompiler::generateUS(Tree sig, const tvec& w) ValueInst* InstructionsCompiler::generateDS(Tree sig, const tvec& w) { - // Create a class unique counter - if (fDSCounter == "") { - fDSCounter = "fDSCounter"; - pushDeclare(IB::genDecStructVar(fDSCounter, IB::genInt32Typed())); - pushClearMethod(IB::genStoreStructVar(fDSCounter, IB::genInt32NumInst(0))); - - FIRIndex value = FIRIndex(IB::genLoadStructVar(fDSCounter)) + 1; - pushPostComputeDSPMethod(IB::genStoreStructVar(fDSCounter, value)); - } - // 1/ We extract the clock, the inputs and the outputs signals // form w = [clock, input1, input2, ..., nil, output1, output2, ...] faustassert(w.size() > 2); @@ -3686,7 +3695,7 @@ ValueInst* InstructionsCompiler::generateDS(Tree sig, const tvec& w) // 3/ We then compile the clock signal and open an ds statement // fClass->addExecCode(Statement("", subst("if ($0) {", CS(clock)))); - fContainer->getCurLoop()->openDSblock(CS(clock), fDSCounter); + fContainer->getCurLoop()->openDSblock(CS(clock), declareRetrieveDSName(clock)); // 4/ Compute the scheduling of the output signals of the ds circuit std::vector V = ondemandCompilationOrder(outputs); diff --git a/compiler/generator/instructions_compiler.hh b/compiler/generator/instructions_compiler.hh index f9aa16d230..3d55f0a5c2 100644 --- a/compiler/generator/instructions_compiler.hh +++ b/compiler/generator/instructions_compiler.hh @@ -46,6 +46,8 @@ class InstructionsCompiler : public virtual Garbageable { property fCompileProperty; property fVectorProperty; property fIotaProperty; // IOTA associated to a specific ondemand clock signal + property + fDSProperty; // Downsampling counter associated to a specific downsampling block property> fStaticInitProperty; property> fInstanceInitProperty; property fTableProperty; @@ -64,8 +66,6 @@ class InstructionsCompiler : public virtual Garbageable { // Several 'IOTA' variables may be needed when subcontainers are inlined in the main module std::string fCurrentIOTA; - std::string fDSCounter; - UITree fUITree; Description* fDescription; @@ -241,6 +241,7 @@ class InstructionsCompiler : public virtual Garbageable { virtual ValueInst* generateXtended(Tree sig); virtual ValueInst* generateDelayAccess(Tree sig, Tree arg, Tree delay); std::string declareRetrieveIotaName(Tree clock); + std::string declareRetrieveDSName(Tree clock); ValueInst* generateDelayAccess(Tree sig, Tree arg, int delay); ValueInst* generateDelayAccess(Tree sig, Tree arg, ValueInst* delayidx); diff --git a/compiler/propagate/propagate.cpp b/compiler/propagate/propagate.cpp index 9fcd59bfbc..d75be75736 100644 --- a/compiler/propagate/propagate.cpp +++ b/compiler/propagate/propagate.cpp @@ -282,13 +282,22 @@ static siglist realPropagate(Tree clockenv, Tree slotenv, Tree path, Tree box, c string vname = string(tree2str(name)); if ((clockenv != gGlobal->nil) && ((vname == "fSamplingFreq") || (vname == "fSamplingRate"))) { - Tree clock = hd(clockenv); - Tree us_ds = hd(tl(clockenv)); - if (us_ds == tree("Upsampling")) { - return makeList(sigMul(sigFConst(type, name, file), clock)); - } else if (us_ds == tree("Downsampling")) { - return makeList(sigDiv(sigFConst(type, name, file), clock)); - } + + Tree adapted_sr = sigFConst(type, name, file); + Tree clocks = clockenv; + // Unroll the stack of all US/DS to compute the adapted SR + do { + Tree sr_factor = hd(clocks); + Tree us_ds = hd(tl(clocks)); + if (us_ds == tree("Upsampling")) { + adapted_sr = sigMul(adapted_sr, sr_factor); + } else if (us_ds == tree("Downsampling")) { + adapted_sr = sigDiv(adapted_sr, sr_factor); + } + clocks = tl(tl(clocks)); + } while (clocks != gGlobal->nil); + + return makeList(simplify(adapted_sr)); } return makeList(sigFConst(type, name, file)); diff --git a/compiler/signals/signals.cpp b/compiler/signals/signals.cpp index 8cecadec17..c81045970d 100644 --- a/compiler/signals/signals.cpp +++ b/compiler/signals/signals.cpp @@ -1175,8 +1175,8 @@ LIBFAUST_API Tree sigClocked(Tree clock, Tree y) // y is already annotated with the clock h return y; } else { - std::cerr << "We have a problem of clocks, new clock : " << *clock - << " is different form existing clock " << *h2 << std::endl; + std::cerr << "ASSERT : we have a problem of clocks, new clock : " << *clock + << " is different from existing clock " << *h2 << std::endl; faustassert(false); } } else {