X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/7af5c69c22148510cf8f042552018c9b966860cd..df84660fd98b39737692d57b68c8b2c2d34af0f1:/FunctionalBlock.cpp?ds=sidebyside diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 23d43b9..7be000a 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -22,8 +22,18 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference else { implementation = reference->getImplementations().at(0); } + lengthAP = -1; + lengthCP = -1; + lengthIP = -1; + lengthOP = -1; + lengthPP = -1; + delta = -1; + evaluator = NULL; } +FunctionalBlock::~FunctionalBlock() { + if (evaluator != NULL) delete evaluator; +} void FunctionalBlock::parametersValidation(QList* checkedBlocks, QList *blocksToConfigure) { /* @@ -109,93 +119,135 @@ QString FunctionalBlock::getReferenceHashMd5() { return ((ReferenceBlock *)reference)->getHashMd5(); } -bool FunctionalBlock::createPatterns() { +void FunctionalBlock::createPatterns() throw(Exception) { 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 (evaluator == NULL) evaluator = new ArithmeticEvaluator(); if (! isGeneratorBlock()) { - if (ok) ok = ok & createConsumptionPattern(); - if (ok) ok = ok & createProductionCounter(); + try { + createDelta(); + createConsumptionPattern(); + createProductionCounter(); + } + catch(Exception e) { + throw(e); // rethrow e + } + } + try { + createProductionPattern(); + } + catch(Exception e) { + throw(e); + } + cout << "PP of " << qPrintable(name) << endl; + QMapIterator* > it(productionPattern); + while (it.hasNext()) { + it.next(); + QList* pat = it.value(); + foreach(char c, *pat) cout << (int)c; + cout << endl; } - if (ok) ok = ok & createProductionPattern(); - delete evaluator; - return ok; } -bool FunctionalBlock::createDelta() { +void FunctionalBlock::createDelta() throw(Exception) { static QString fctName = "FunctionalBlock::createDelta()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - QString deltaStr = implementation->getDelta(); + QString deltaStr = implementation->getDelta(); cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl; + if (deltaStr.isEmpty()) { + delta = -1; + return; + } - // look for parameter names - bool ok = true; - double result = evaluateExpression(deltaStr, &ok); - if (!ok) return false; - + // look for parameter names + double result = 0; + try { + result = evaluateExpression(deltaStr); + } + catch(Exception e) { + throw(e); + } delta = result; cout << "delta = " << delta << endl; - - return true; } -bool FunctionalBlock::createConsumptionPattern() { +void FunctionalBlock::createConsumptionPattern() throw(Exception) { static QString fctName = "FunctionalBlock::createConsumptionPattern()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - bool ok = true; + lengthCP = -1; QHash consPattern = implementation->getConsumptionPattern(); foreach(AbstractInterface* iface, getControlInputs()) { FunctionalInterface* connIface = AI_TO_FUN(iface); QString refName = connIface->getReference()->getName(); if (! consPattern.contains(refName)) { + throw(Exception(NO_IFACE_CP)); cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl; - return false; } - QList* pattern = expandPattern(consPattern.value(refName),&ok); - - if (!ok) return false; - consumptionPattern.insert(connIface,pattern); - } - return true; + QList* pattern = NULL; + try { + pattern = expandPattern(consPattern.value(refName)); + } + catch(Exception e) { + throw(e); + } + consumptionPattern.insert(connIface,pattern); + if (lengthCP == -1) { + lengthCP = pattern->size(); + } + else { + if (pattern->size() != lengthCP) { + throw(Exception(INVALID_IFACE_CP_LENGTH)); + } + } + } } -bool FunctionalBlock::createProductionPattern() { +void FunctionalBlock::createProductionPattern() throw(Exception){ static QString fctName = "FunctionalBlock::createProductionPattern()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - bool ok = true; + lengthPP = -1; 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; + throw(Exception(NO_IFACE_PP)); } - QList* pattern = expandPattern(prodPattern.value(refName),&ok); - if (!ok) return false; - productionPattern.insert(connIface,pattern); - } - return true; + QList* pattern = NULL; + try { + pattern = expandPattern(prodPattern.value(refName)); + } + catch(Exception e) { + throw(e); + } + productionPattern.insert(connIface,pattern); + if (lengthPP == -1) { + lengthPP = pattern->size(); + } + else { + if (pattern->size() != lengthPP) { + throw(Exception(INVALID_IFACE_PP_LENGTH)); + } + } + } } -bool FunctionalBlock::createProductionCounter() { +void FunctionalBlock::createProductionCounter() throw(Exception) { static QString fctName = "FunctionalBlock::createProductionCounter()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; @@ -213,14 +265,20 @@ bool FunctionalBlock::createProductionCounter() { s.remove(0,1); s.chop(1); QStringList gen = s.split(":"); - if (gen.size() != 3) return false; + if (gen.size() != 3) { + throw(Exception(INVALID_IFACE_PC)); + } 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; + for(int i=0;i<3;i++) { + double result = 0.0; + try { + result = evaluateExpression(gen.at(i)); + } + catch(Exception e) { + throw(e); + } if (i==0) start = result; else if (i==1) nb = result; else if (i==2) step = result; @@ -229,11 +287,14 @@ bool FunctionalBlock::createProductionCounter() { productionCounter.append(start+j*step); } } - else { - bool okVal; - double result = evaluateExpression(s,&okVal); - - if (!okVal) return false; + else { + double result = 0.0; + try { + result = evaluateExpression(s); + } + catch(Exception e) { + throw(e); + } productionCounter.append(result); } } @@ -241,11 +302,9 @@ bool FunctionalBlock::createProductionCounter() { cout << val << ","; } cout << endl; - - return true; } -QList* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) { +QList* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exception) { static QString fctName = "FunctionalBlock::expandPattern()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; @@ -254,32 +313,42 @@ QList* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) QList lst; QString p = patternIn; p.append(')'); - int offset = 0; + int offset = 0; QList* patternOut = new QList(); - expandPatternRecur(p,&offset,ok,patternOut); + try { + patternOut->append(expandPatternRecur(p,&offset)); + } + catch(Exception e) { + throw(e); + } + return patternOut; } -void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, bool *ok, QList* patternOut) { +QList FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset) throw(Exception) { + QList patternOut; + while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) { QChar c = patternIn.at(*offset); if (c == '(') { *offset += 1; - expandPatternRecur(patternIn,offset, ok, patternOut); - if (!ok) { - return; + try { + patternOut.append(expandPatternRecur(patternIn,offset)); + } + catch(Exception e) { + throw(e); } } else if (c == '0') { - patternOut->append(0); + patternOut.append(0); } else if (c == '1') { - patternOut->append(1); + patternOut.append(1); } else if (c == 'X') { - patternOut->append(-1); + patternOut.append(-1); } else if (c == '{') { *offset += 1; @@ -289,19 +358,21 @@ void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, *offset += 1; } if (*offset == patternIn.size()) { - *ok = false; - return; + throw(Exception(INVALID_IFACE_PATTERN)); + } + double repeat = 0; + try { + repeat = evaluateExpression(expr); + } + catch(Exception e) { + throw(e); } - double repeat = evaluateExpression(expr,ok); - if (!ok) { - return; - } // repeat just the last value in currentGroup - char last = patternOut->last(); + char last = patternOut.last(); //cout << "repeat last char " << repeat << " times : " << (int)last << endl; for(int i=1;i<(int)repeat;i++) { - patternOut->append(last); + patternOut.append(last); } } *offset += 1; @@ -316,34 +387,34 @@ void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, *offset += 1; } if (*offset == patternIn.size()) { - *ok = false; - return; + throw(Exception(INVALID_IFACE_PATTERN)); } - double repeat = evaluateExpression(expr,ok); - if (!ok) { - return; + double repeat = 0; + try { + repeat = evaluateExpression(expr); + } + catch(Exception e) { + throw(e); } /* cout << "repeat last group " << repeat << " times : "; foreach (char c, currentGroup) cout <<(int)c; cout << endl; */ - QList single = *patternOut; + QList single = patternOut; for(int i=1;i<(int)repeat;i++) { - patternOut->append(single); + patternOut.append(single); } - } - //*offset += 1; - return; + } + return patternOut; } -double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) { +double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exception) { 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(); @@ -352,34 +423,191 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) 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; + throw(Exception(EVAL_PARAM_UNKNOWN)); } bool okVal; int val = param->getDoubleValue(&okVal); if (!okVal) { - cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl; - *ok = false; - return 0.0; + throw(Exception(EVAL_PARAM_NOVALUE)); } vars.insert(name,(double)val); } evaluator->setVariablesValue(vars); - double result; + double result = 0.0; try { result = evaluator->evaluate(); } catch(int index) { cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl; - *ok = false; - return 0.0; + throw(Exception(EVAL_INVALID_EXPR)); } return result; } -bool FunctionalBlock::computeOutputPattern(int nbExec) { +void FunctionalBlock::createInputPattern() throw(Exception) { + static QString fctName = "FunctionalBlock::createInputPattern())"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + lengthIP = -1; + foreach(AbstractInterface* iface, getControlInputs()) { + ConnectedInterface* connIface = AI_TO_CON(iface); + QList* out = connIface->getConnectedFrom()->getOutputPattern(); + if (out->size() == 0) { + clearInputPattern(); + throw(Exception(NO_IFACE_IP)); + } + if (lengthIP == -1) { + lengthIP = out->size(); + } + else { + if (out->size() < lengthIP) lengthIP = out->size(); + } + + QList* in = new QList(*out); + foreach(char c, *in) { + cout << (int)c; + } + cout << endl; + inputPattern.insert(connIface,in); + } + // search the last valid group in IP, + while(! isValidDataGroup(inputPattern,lengthIP-1)) { + //removeDataGroup(inputPattern,lengthIP-1); + lengthIP -= 1; + } +} + +void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) { + static QString fctName = "FunctionalBlock::createAdmittance()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + // firstly, copy CP in AP + QMapIterator* > iterC(consumptionPattern); + while (iterC.hasNext()) { + iterC.next(); + QList* pattern = new QList(*(iterC.value())); + admittance.insert(iterC.key(), pattern); + } + lengthAP = lengthCP; + int clock = 0; + cout << "trigger 1 at c.c. 0" << endl; + for(int i=1;i* > iterA(admittance); + while (iterA.hasNext()) { + iterA.next(); + QList* pattern = iterA.value(); + for(int i=0;isize();i++) { + if (pattern->at(i) == -1) pattern->replace(i,0); + cout << (int)(pattern->at(i)); + } + cout << endl; + } +} + +void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) { + static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + // firstly, create input pattern + try { + createInputPattern(); + } + catch(Exception e) { + throw(e); + } + int nbExec = createTriggers(); + cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl; + + try { + createAdmittance(nbExec); + } + catch(Exception e) { + cout << "cannot create admittance" << endl; + throw(e); + } + + int clock = 0; // index in IP + int i = 0; // index in AP + while ((clock < lengthIP) && (i < lengthAP)) { + + // if AP is a valid group, search for the next valid group in IP + if (isValidDataGroup(admittance,i)) { + while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++; + if (clock == lengthIP) { + cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl; + throw(Exception(IP_END_NULLCOL)); + } + } + /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or + are both null columns + */ + if (! samePatterns(inputPattern,clock,admittance,i)) { + cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl; + throw(Exception(IP_AP_NOTCOMPAT)); // IP and AP not compatible + } + clock++; + i++; + } + if (clock < lengthIP) { + throw(Exception(AP_TOO_SHORT)); + cerr << "Abnormal case: AP is to short" << endl; + } +} + +void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) { static QString fctName = "FunctionalBlock::computeOutputPattern()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; @@ -407,48 +635,23 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { else { cout << "computing output pattern of " << qPrintable(name) << endl; - // collect the input patterns for each input - QMap* > inputPattern; - int minLen = -1; - foreach(AbstractInterface* iface, getControlInputs()) { - ConnectedInterface* connIface = AI_TO_CON(iface); - QList* out = connIface->getConnectedFrom()->getOutputPattern(); - if (minLen == -1) { - minLen = out->size(); + // in case of inputPattern not created, do it + if (lengthIP <= 0) { + // collect the input patterns for each input + try { + createInputPattern(); } - else { - if (out->size() < minLen) minLen = out->size(); + catch(Exception e) { + throw(e); } - if (out->size() > 0) { - QList* in = new QList(*out); - foreach(char c, *in) { - cout << (int)c; - } - cout << endl; - - inputPattern.insert(connIface,in); - } - else { - inputPattern.insert(connIface,NULL); - } - } - // if some patterns are not available, end now, returning false - if (minLen == 0) { - QMapIterator* > iterI(inputPattern); - while (iterI.hasNext()) { - iterI.next(); - QList* pattern = iterI.value(); - if (pattern != NULL) delete pattern; - } - return false; - } - cout << "input pattern array initialized with min. len " << minLen << endl; + cout << "input pattern array initialized with min. len " << lengthIP << endl; + } // initialize the output pattern - int lengthOP = 0; + lengthOP = 0; foreach(AbstractInterface* iface, getControlOutputs()) { FunctionalInterface* connIface = AI_TO_FUN(iface); - lengthOP = minLen+productionPattern.value(connIface)->size(); + lengthOP = lengthIP+productionPattern.value(connIface)->size(); QList* pattern = new QList(); for(int i=0;iappend(0); connIface->setOutputPattern(pattern); @@ -459,10 +662,10 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { int clock = 0; nbExec = 0; // search for the beginning of the first execution. - while ((clock < minLen) && (! isValidDataGroup(inputPattern,clock))) clock++; + while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++; cout << "found 1st exec clock: " << clock << endl; - while (clock < minLen) { + while (clock < lengthIP) { // initialize counters for current execution. int p = 0; // index in production pattern int o = 0; // clock+o will give the clock cycle of each output group @@ -480,7 +683,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { int gap = 0; // count the number of extra null columns // search for PC(m) valid input group in IP while (nip < productionCounter.at(m)) { - if (clock+cip < minLen) { + if (clock+cip < lengthIP) { if (isValidDataGroup(inputPattern,clock+cip)) nip += 1; cip += 1; gap += 1; @@ -513,7 +716,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { // search for the next exec. clock += 1; nip = 0; - while ((clock < minLen) && (nip < delta)) { + while ((clock < lengthIP) && (nip < delta)) { if (isValidDataGroup(inputPattern,clock)) nip += 1; if (nip < delta) clock += 1; } @@ -525,13 +728,150 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { lengthOP -= 1; } - // clear input pattern - QMapIterator* > iterI(inputPattern); - while (iterI.hasNext()) { - iterI.next(); - QList* pattern = iterI.value(); - if (pattern != NULL) delete pattern; - } + // clear input pattern + clearInputPattern(); + } +} + +/* + +void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) { + 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); + // create output pattern + QList* pp = productionPattern.value(connIface); + QList* pattern = new QList(*pp); + for(int i=1;iappend(*pp); + // assign pattern to interface + connIface->setOutputPattern(pattern); + // store it in QMap + outputPattern.insert(connIface,pattern); + } + } + else { + cout << "computing output pattern of " << qPrintable(name) << endl; + + // in case of inputPattern not created, do it + if (lengthIP <= 0) { + // collect the input patterns for each input + try { + createInputPattern(); + } + catch(Exception e) { + throw(e); + } + cout << "input pattern array initialized with min. len " << lengthIP << endl; + } + + // initialize the output pattern + lengthOP = 0; + foreach(AbstractInterface* iface, getControlOutputs()) { + FunctionalInterface* connIface = AI_TO_FUN(iface); + lengthOP = lengthIP+productionPattern.value(connIface)->size(); + QList* pattern = new QList(); + for(int i=0;iappend(0); + connIface->setOutputPattern(pattern); + outputPattern.insert(connIface,pattern); + } + cout << "output pattern array initialized" << endl; + + int clock = 0; + nbExec = 0; + // search for the beginning of the first execution. + while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++; + cout << "found 1st exec clock: " << clock << endl; + + while (clock < lengthIP) { + // initialize counters for current execution. + int p = 0; // index in production pattern + int o = 0; // clock+o will give the clock cycle of each output group + int cip = 0; // clock+cip give the clock cycle of an input group + int ccp = 0; // ccp give a column in the consumptio pattern + int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP + int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP + bool cannotCompleteExec = false; + for(int m=0;m* >& patternSrc, int srcCol, const QMap* >& patternDest, int destCol) { + + if (patternSrc.size() != patternDest.size()) return false; + QMapIterator* > iterSrc(patternSrc); + QMapIterator* > iterDest(patternDest); + while (iterSrc.hasNext()) { + iterSrc.next(); + iterDest.next(); + QList* srcPat = iterSrc.value(); + QList* destPat = iterDest.value(); + if (srcCol >= srcPat->size()) return false; + if (destCol >= destPat->size()) return false; + if (srcPat->at(srcCol) != destPat->at(destCol)) return false; } return true; } @@ -598,6 +938,17 @@ void FunctionalBlock::removeDataGroup(QMap *> & } } +void FunctionalBlock::shiftRightPattern(const QMap *> &pattern, int offset) { + QMapIterator* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList* srcPat = iterSrc.value(); + if (offset < srcPat->size()) { + srcPat->insert(offset,0); + } + } +} + bool FunctionalBlock::isValidDataGroup(const QMap *> &pattern, int offset) { QMapIterator* > iterSrc(pattern); while (iterSrc.hasNext()) { @@ -627,6 +978,8 @@ void FunctionalBlock::clearConsumptionPattern() { QList* pattern = iterP.value(); if (pattern != NULL) delete pattern; } + consumptionPattern.clear(); + lengthCP = -1; } void FunctionalBlock::clearProductionPattern() { @@ -636,4 +989,40 @@ void FunctionalBlock::clearProductionPattern() { QList* pattern = iterP.value(); if (pattern != NULL) delete pattern; } + productionPattern.clear(); + lengthPP = -1; } + +void FunctionalBlock::clearInputPattern() { + + QMapIterator* > iterI(inputPattern); + while (iterI.hasNext()) { + iterI.next(); + QList* pattern = iterI.value(); + if (pattern != NULL) delete pattern; + } + inputPattern.clear(); + lengthIP = -1; +} + +int FunctionalBlock::createTriggers() { + triggers.clear(); + /* NB: this method returns the number of executions that have been started + but not necessary completed. + */ + if (delta <= 0) return 0; + int offset = 0; + // search for the first exec. + while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++; + if (offset == lengthIP) return 0; + triggers.append(offset); + int nbGroup = 0; + for(int i = offset;i