X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/8e89ca269960b7bb43ccc054696dfc28e84d409a..48f48e6a26a54751ecd0ab90b10ab972cc5e89cd:/FunctionalBlock.cpp?ds=sidebyside diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 5731794..0db21c4 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -5,6 +5,7 @@ #include "FunctionalInterface.h" #include "ReferenceInterface.h" #include "BlockParameter.h" +#include "ArithmeticEvaluator.h" FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) : AbstractBlock() { @@ -114,82 +115,311 @@ QString FunctionalBlock::getReferenceHashMd5() { } bool FunctionalBlock::createPatterns() { + static QString fctName = "FunctionalBlock::createPatterns()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + cout << "create patterns for block " << qPrintable(name) << endl; evaluator = new ArithmeticEvaluator(); bool ok = true; ok = ok & createDelta(); - if (ok) ok = ok & createConsumptionPattern(); - if (ok) ok = ok & createProductionCounter(); + if (! isGeneratorBlock()) { + if (ok) ok = ok & createConsumptionPattern(); + if (ok) ok = ok & createProductionCounter(); + } if (ok) ok = ok & createProductionPattern(); delete evaluator; return ok; } bool FunctionalBlock::createDelta() { - QString delta = implementation->getDelta(); - cout << "delta for " << qPrintable(name) << " = " << qPrintable(delta) << endl; + static QString fctName = "FunctionalBlock::createDelta()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + QString deltaStr = implementation->getDelta(); + cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl; // look for parameter names - QHash vars; - QRegularExpression re("[$][a-zA-Z0-9_]+"); - QRegularExpressionMatchIterator matcher = re.globalMatch(delta); - while(matcher.hasNext()) { - QRegularExpressionMatch m = matcher.next(); - QString var = m.captured(0); - cout << qPrintable(var) << endl; - vars.insert(var,0.0); - } - QHashIterator iterV(vars); - while (iterV.hasNext()) { - iterV.next(); - QString var = iterV.key(); - QString paramName = var.remove(0,1); - BlockParameter* param = reference->getParameterFromName(paramName); - cout << "param = " << qPrintable(param->getStringValue()) << endl; - if (param == NULL) { - cerr << "found an unknown parameter in delta"<< endl; - return false; - } - bool ok; - int val = param->getIntValue(&ok); - vars.insert(var,(double)val); - } - cout << "set expr " << endl; - evaluator->setExpression(delta); - cout << "set vars " << endl; - evaluator->setVariablesValue(vars); - double result = evaluator->evaluate(); - cout << "delta = " << result << endl; + bool ok = true; + double result = evaluateExpression(deltaStr, &ok); + if (!ok) return false; + + delta = result; + cout << "delta = " << delta << endl; return true; } bool FunctionalBlock::createConsumptionPattern() { + static QString fctName = "FunctionalBlock::createConsumptionPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + bool ok = true; + QHash consPattern = implementation->getConsumptionPattern(); + + foreach(AbstractInterface* iface, getControlInputs()) { + FunctionalInterface* connIface = AI_TO_FUN(iface); + QString refName = connIface->getReference()->getName(); + if (! consPattern.contains(refName)) { + cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl; + return false; + } + QList pattern = expandPattern(consPattern.value(refName),&ok); + + if (!ok) return false; + connIface->setConsumptionPattern(pattern); + cout << qPrintable(refName) << " consumption pattern = "; + foreach(char c, pattern) { + cout << (int)c << " "; + } + cout << endl; + + } return true; } -bool FunctionalBlock::createProductionPattern() { +bool FunctionalBlock::createProductionPattern() { + static QString fctName = "FunctionalBlock::createProductionPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + bool ok = true; + QHash prodPattern = implementation->getProductionPattern(); + + foreach(AbstractInterface* iface, getControlOutputs()) { + FunctionalInterface* connIface = AI_TO_FUN(iface); + QString refName = connIface->getReference()->getName(); + if (! prodPattern.contains(refName)) { + cerr << "no production pattern for reference interface " << qPrintable(refName) << endl; + return false; + } + QList pattern = expandPattern(prodPattern.value(refName),&ok); + if (!ok) return false; + connIface->setProductionPattern(pattern); + cout << qPrintable(refName) << " production pattern = "; + foreach(char c, pattern) { + cout << (int)c << " "; + } + cout << endl; + + } return true; } bool FunctionalBlock::createProductionCounter() { + static QString fctName = "FunctionalBlock::createProductionCounter()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + QStringList counterParts = implementation->getProductionCounter().split(","); + foreach(QString s, counterParts) { + cout << "cont part = " << qPrintable(s) << endl; + bool ok; + double val = s.toDouble(&ok); + if (ok) { + productionCounter.append(val); + } + else if (s.at(0) == '{') { + s.remove(0,1); + s.chop(1); + QStringList gen = s.split(":"); + if (gen.size() != 3) return false; + int start = 0; + int nb = 0; + int step = 0; + for(int i=0;i<3;i++) { + bool okVal; + double result = evaluateExpression(gen.at(i),&okVal); + if (!okVal) return false; + if (i==0) start = result; + else if (i==1) nb = result; + else if (i==2) step = result; + } + for(int j=0;j FunctionalBlock::expandPattern(const QString& pattern, bool* ok) { + static QString fctName = "FunctionalBlock::expandPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + QList lst; + QString p = pattern; + p.append(')'); + int offset = 0; + lst = expandPatternRecur(p,&offset,ok); + return lst; +} + +QList FunctionalBlock::expandPatternRecur(const QString& pattern, int *offset, bool *ok) { + + QList currentGroup; + + while ((*offset < pattern.size()) && (pattern.at(*offset) != ')')) { + + QChar c = pattern.at(*offset); + if (c == '(') { + *offset += 1; + currentGroup += expandPatternRecur(pattern,offset, ok); + if (!ok) { + return currentGroup; + } + } + else if (c == '0') { + currentGroup.append(0); + } + else if (c == '1') { + currentGroup.append(1); + } + else if (c == 'X') { + currentGroup.append(-1); + } + else if (c == '{') { + *offset += 1; + QString expr = ""; + while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) { + expr += pattern.at(*offset); + *offset += 1; + } + if (*offset == pattern.size()) { + *ok = false; + return currentGroup; + } + double repeat = evaluateExpression(expr,ok); + if (!ok) { + return currentGroup; + } + // repeat just the last value in currentGroup + char last = currentGroup.last(); + //cout << "repeat last char " << repeat << " times : " << (int)last << endl; + + for(int i=1;i<(int)repeat;i++) { + currentGroup += last; + } + } + *offset += 1; + } + + // must check if after ), there is a { + if ((*offset < pattern.size()-1) && (pattern.at(*offset+1) == '{')) { + *offset += 2; + QString expr = ""; + while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) { + expr += pattern.at(*offset); + *offset += 1; + } + if (*offset == pattern.size()) { + *ok = false; + return currentGroup; + } + double repeat = evaluateExpression(expr,ok); + if (!ok) { + return currentGroup; + } + /* + cout << "repeat last group " << repeat << " times : "; + foreach (char c, currentGroup) cout <<(int)c; + cout << endl; + */ + QList single = currentGroup; + for(int i=1;i<(int)repeat;i++) { + currentGroup += single; + } + } + //*offset += 1; + return currentGroup; +} + +double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) { + static QString fctName = "FunctionalBlock::evaluateExpression()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + *ok = true; + QHash vars; + evaluator->setExpression(expression); + QList varNames = evaluator->getVariableNames(); + foreach (QString name, varNames) { + QString paramName = name; + paramName.remove(0,1); + BlockParameter* param = reference->getParameterFromName(paramName); + if (param == NULL) { + cerr << "found an unknown parameter in delta"<< endl; + *ok = false; + return 0.0; + } + bool okVal; + int val = param->getDoubleValue(&okVal); + if (!okVal) { + cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl; + *ok = false; + return 0.0; + } + vars.insert(name,(double)val); + } + evaluator->setVariablesValue(vars); + double result; + try { + result = evaluator->evaluate(); + } + catch(int index) { + cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl; + *ok = false; + return 0.0; + } + return result; +} + bool FunctionalBlock::computeOutputPattern(int nbExec) { + static QString fctName = "FunctionalBlock::computeOutputPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif /* case 1: the block is a generator for which output pattern must be computed for a nbExec following executions */ + if (nbExec > 0) { + cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl; foreach(AbstractInterface* iface, getControlOutputs()) { + FunctionalInterface* connIface = AI_TO_FUN(iface); QList pattern; - for(int i=0;igetProductionPattern(); - iface->setOutputPattern(pattern); + for(int i=0;igetProductionPattern(); + connIface->setOutputPattern(pattern); } } else { - // initialize consumption and production patterns + cout << "computing output pattern of " << qPrintable(name) << endl; + + // initialize consumption and production patterns initConsumptionPattern(); initProductionPattern(); @@ -199,7 +429,8 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { inputPattern = new char*[nbConsumingPorts]; int minLen = -1; foreach(AbstractInterface* iface, getControlInputs()) { - QList in = iface->getConnectedFrom()->getOutputPattern(); + ConnectedInterface* connIface = AI_TO_CON(iface); + QList in = connIface->getConnectedFrom()->getOutputPattern(); if (minLen == -1) { minLen = in.size(); } @@ -224,22 +455,26 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { delete [] inputPattern; return false; } + cout << "input pattern array initialized with min. len " << minLen << endl; // initialize the output pattern char** outputPattern = NULL; outputPattern = new char*[nbProducingPorts]; int lengthOP = 0; idIface = 0; foreach(AbstractInterface* iface, getControlOutputs()) { - lengthOP = minLen+iface->getProductionPattern().size(); + FunctionalInterface* connIface = AI_TO_FUN(iface); + lengthOP = minLen+connIface->getProductionPattern().size(); outputPattern[idIface] = new char[lengthOP]; memset(outputPattern[idIface],0,lengthOP); idIface += 1; } + cout << "output pattern array initialized" << endl; int clock = 0; nbExec = 0; // search for the beginning of the first execution. - while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++; + while ((clock < minLen) && (! isValidDataGroup(inputPattern,nbConsumingPorts,clock))) clock++; + cout << "found 1st exec clock: " << clock << endl; while (clock < minLen) { // initialize counters for current execution. @@ -274,7 +509,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { // search for PC(m) valid input group in IP while (ncp < productionCounter.at(m)) { - if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1; + if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) ncp += 1; ccp += 1; gap -= 1; } @@ -300,12 +535,15 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { // find the last valid output data group while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1; + //for(int i=0;i pattern; for(int i=0;isetOutputPattern(pattern); + connIface->setOutputPattern(pattern); idIface += 1; } @@ -358,14 +596,19 @@ void FunctionalBlock::clearProductionPattern() { } void FunctionalBlock::initConsumptionPattern() { + static QString fctName = "FunctionalBlock::initConsumptionPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + if (consumptionPattern != NULL) clearConsumptionPattern(); nbConsumingPorts = getControlInputs().size(); int idIface = 0; consumptionPattern = new char*[nbConsumingPorts]; foreach(AbstractInterface* iface, getControlInputs()) { - - QList in = iface->getConsumptionPattern(); + FunctionalInterface* connIface = AI_TO_FUN(iface); + QList in = connIface->getConsumptionPattern(); lengthCP = in.size(); // normally, all inputs have the same lenght for CP consumptionPattern[idIface] = new char[lengthCP]; int i = 0; @@ -375,14 +618,19 @@ void FunctionalBlock::initConsumptionPattern() { } void FunctionalBlock::initProductionPattern() { + static QString fctName = "FunctionalBlock::initProductionPattern()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + if (productionPattern != NULL) clearProductionPattern(); nbProducingPorts = getControlOutputs().size(); int idIface = 0; productionPattern = new char*[nbProducingPorts]; foreach(AbstractInterface* iface, getControlOutputs()) { - - QList in = iface->getProductionPattern(); + FunctionalInterface* connIface = AI_TO_FUN(iface); + QList in = connIface->getProductionPattern(); lengthPP = in.size(); // normally, all inputs have the same lenght for PP productionPattern[idIface] = new char[lengthPP]; int i = 0;