X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/48f48e6a26a54751ecd0ab90b10ab972cc5e89cd..84eeae848c9d322ea4c935b8ec7338f69becbc10:/FunctionalBlock.cpp diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 0db21c4..66e89b4 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -14,12 +14,7 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference reference = _reference; parent = _parent; name = reference->getName(); - consumptionPattern = NULL; - lengthCP = 0; - nbConsumingPorts = 0; - productionPattern = NULL; - lengthPP = 0; - nbProducingPorts = 0; + if (reference->getImplementations().isEmpty()) { implementation = NULL; cout << "block has no implementation" << endl; @@ -27,6 +22,12 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference else { implementation = reference->getImplementations().at(0); } + lengthAP = -1; + lengthCP = -1; + lengthIP = -1; + lengthOP = -1; + lengthPP = -1; + delta = -1; } @@ -122,10 +123,10 @@ bool FunctionalBlock::createPatterns() { cout << "create patterns for block " << qPrintable(name) << endl; evaluator = new ArithmeticEvaluator(); - bool ok = true; - ok = ok & createDelta(); + bool ok = true; if (! isGeneratorBlock()) { - if (ok) ok = ok & createConsumptionPattern(); + ok = ok & createDelta(); + if (ok) ok = ok & createConsumptionPattern(); if (ok) ok = ok & createProductionCounter(); } if (ok) ok = ok & createProductionPattern(); @@ -139,8 +140,12 @@ bool FunctionalBlock::createDelta() { 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 true; + } // look for parameter names bool ok = true; @@ -159,6 +164,7 @@ bool FunctionalBlock::createConsumptionPattern() { cout << "call to " << qPrintable(fctName) << endl; #endif + lengthCP = -1; bool ok = true; QHash consPattern = implementation->getConsumptionPattern(); @@ -169,16 +175,15 @@ bool FunctionalBlock::createConsumptionPattern() { cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl; return false; } - QList pattern = expandPattern(consPattern.value(refName),&ok); - + 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 << " "; + consumptionPattern.insert(connIface,pattern); + if (lengthCP == -1) { + lengthCP = pattern->size(); + } + else { + if (pattern->size() != lengthCP) return false; } - cout << endl; - } return true; } @@ -189,6 +194,7 @@ bool FunctionalBlock::createProductionPattern() { cout << "call to " << qPrintable(fctName) << endl; #endif + lengthPP = -1; bool ok = true; QHash prodPattern = implementation->getProductionPattern(); @@ -199,15 +205,15 @@ bool FunctionalBlock::createProductionPattern() { cerr << "no production pattern for reference interface " << qPrintable(refName) << endl; return false; } - QList pattern = expandPattern(prodPattern.value(refName),&ok); + 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 << " "; + productionPattern.insert(connIface,pattern); + if (lengthPP == -1) { + lengthPP = pattern->size(); + } + else { + if (pattern->size() != lengthPP) return false; } - cout << endl; - } return true; } @@ -262,97 +268,96 @@ bool FunctionalBlock::createProductionCounter() { return true; } -QList FunctionalBlock::expandPattern(const QString& pattern, bool* ok) { +QList* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) { static QString fctName = "FunctionalBlock::expandPattern()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif QList lst; - QString p = pattern; + QString p = patternIn; p.append(')'); int offset = 0; - lst = expandPatternRecur(p,&offset,ok); - return lst; + QList* patternOut = new QList(); + expandPatternRecur(p,&offset,ok,patternOut); + return patternOut; } -QList FunctionalBlock::expandPatternRecur(const QString& pattern, int *offset, bool *ok) { - - QList currentGroup; +void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, bool *ok, QList* patternOut) { - while ((*offset < pattern.size()) && (pattern.at(*offset) != ')')) { + while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) { - QChar c = pattern.at(*offset); + QChar c = patternIn.at(*offset); if (c == '(') { *offset += 1; - currentGroup += expandPatternRecur(pattern,offset, ok); + expandPatternRecur(patternIn,offset, ok, patternOut); if (!ok) { - return currentGroup; + return; } } else if (c == '0') { - currentGroup.append(0); + patternOut->append(0); } else if (c == '1') { - currentGroup.append(1); + patternOut->append(1); } else if (c == 'X') { - currentGroup.append(-1); + patternOut->append(-1); } else if (c == '{') { *offset += 1; QString expr = ""; - while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) { - expr += pattern.at(*offset); + while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) { + expr += patternIn.at(*offset); *offset += 1; } - if (*offset == pattern.size()) { + if (*offset == patternIn.size()) { *ok = false; - return currentGroup; + return; } double repeat = evaluateExpression(expr,ok); if (!ok) { - return currentGroup; + return; } // repeat just the last value in currentGroup - char last = currentGroup.last(); + char last = patternOut->last(); //cout << "repeat last char " << repeat << " times : " << (int)last << endl; for(int i=1;i<(int)repeat;i++) { - currentGroup += last; + patternOut->append(last); } } *offset += 1; } // must check if after ), there is a { - if ((*offset < pattern.size()-1) && (pattern.at(*offset+1) == '{')) { + if ((*offset < patternIn.size()-1) && (patternIn.at(*offset+1) == '{')) { *offset += 2; QString expr = ""; - while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) { - expr += pattern.at(*offset); + while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) { + expr += patternIn.at(*offset); *offset += 1; } - if (*offset == pattern.size()) { + if (*offset == patternIn.size()) { *ok = false; - return currentGroup; + return; } double repeat = evaluateExpression(expr,ok); if (!ok) { - return currentGroup; + return; } /* cout << "repeat last group " << repeat << " times : "; foreach (char c, currentGroup) cout <<(int)c; cout << endl; */ - QList single = currentGroup; + QList single = *patternOut; for(int i=1;i<(int)repeat;i++) { - currentGroup += single; + patternOut->append(single); } } //*offset += 1; - return currentGroup; + return; } double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) { @@ -382,7 +387,8 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) return 0.0; } vars.insert(name,(double)val); - } + } + evaluator->setVariablesValue(vars); double result; try { @@ -396,6 +402,152 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) return result; } +void FunctionalBlock::createInputPattern() { + 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 (lengthIP == -1) { + lengthIP = out->size(); + } + else { + if (out->size() < lengthIP) lengthIP = out->size(); + } + 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); + } + } +} + +bool FunctionalBlock::createAdmittance(int nbExec) { + static QString fctName = "FunctionalBlock::createAdmittance()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + bool ok = true; + // 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); + } + } + return true; +} + +bool FunctionalBlock::checkInputPatternCompatibility() { + static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + bool ok = true; + // firstly, create input pattern + createInputPattern(); + // if some patterns are not available, end now, returning false + if (lengthIP == 0) { + clearInputPattern(); + return false; + } + int nbExec = getNumberOfExecution(); + ok = createAdmittance(nbExec); + if (!ok) return false; + + int clock = 0; // index in IP + int i = 0; // index in AP + while (clock < lengthIP) { + if (samePatterns(inputPattern,clock,admittance,i)) { + clock++; + i++; + } + else { + if (isValidDataGroup(admittance,i)) { + + } + else { + // IP and AP are not equal and AP is a valid group -> not compatible + return false; + } + + } + } + return true; +} + bool FunctionalBlock::computeOutputPattern(int nbExec) { static QString fctName = "FunctionalBlock::computeOutputPattern()"; #ifdef DEBUG_FCTNAME @@ -411,72 +563,50 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { 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(); + // 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; - // initialize consumption and production patterns - initConsumptionPattern(); - initProductionPattern(); - - // collect the input patterns for each input - char** inputPattern = NULL; - int idIface = 0; - inputPattern = new char*[nbConsumingPorts]; - int minLen = -1; - foreach(AbstractInterface* iface, getControlInputs()) { - ConnectedInterface* connIface = AI_TO_CON(iface); - QList in = connIface->getConnectedFrom()->getOutputPattern(); - if (minLen == -1) { - minLen = in.size(); + // in case of inputPattern not created, do it + if (lengthIP <= 0) { + // collect the input patterns for each input + createInputPattern(); + // if some patterns are not available, end now, returning false + if (lengthIP == 0) { + clearInputPattern(); + return false; } - else { - if (in.size() < minLen) minLen = in.size(); - } - if (in.size() > 0) { - inputPattern[idIface] = new char[in.size()]; - int i = 0; - foreach(char c, in) inputPattern[idIface][i++] = c; - } - else { - inputPattern[idIface] = NULL; - } - idIface += 1; - } - // if some patterns are not available, ens now, returning false - if (minLen == 0) { - for(int i=0;igetProductionPattern().size(); - outputPattern[idIface] = new char[lengthOP]; - memset(outputPattern[idIface],0,lengthOP); - idIface += 1; + 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 < minLen) && (! isValidDataGroup(inputPattern,nbConsumingPorts,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 @@ -487,15 +617,15 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { bool cannotCompleteExec = false; for(int m=0;m pattern; - for(int i=0;isetOutputPattern(pattern); - idIface += 1; - } - - // clear inputPattern and outputPattern - for(int i=0;i* >& patternSrc, int srcCol, const QMap* >& patternDest, int destCol) { - for(int i=0;i* > 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 false; + return true; } -void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) { - - for (int i=0;i* >& patternSrc, int srcCol, 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) == -1) && (destPat->at(destCol) == 1)) return false; + if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false; + } + return true; +} + +void FunctionalBlock::combinePatterns(const QMap* >& patternSrc, int srcCol, QMap* > patternDest, int destCol) { + if (patternSrc.size() != patternDest.size()) return; + 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; + if (destCol >= destPat->size()) return; + if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return; + if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return; + destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol)); + } +} + +void FunctionalBlock::appendToPattern(const QMap* >& patternSrc, int srcCol, QMap* > patternDest, int nbCols) { + if (patternSrc.size() != patternDest.size()) return; + QMapIterator* > iterSrc(patternSrc); + QMapIterator* > iterDest(patternDest); + while (iterSrc.hasNext()) { + iterSrc.next(); + iterDest.next(); + QList* srcPat = iterSrc.value(); + QList* destPat = iterDest.value(); + int i=0; + while ((srcCol+i < srcPat->size()) && (iappend(srcPat->at(srcCol+i)); + i++; + } + } +} + +void FunctionalBlock::removeDataGroup(QMap *> &pattern, int offset) { + QMapIterator* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList* srcPat = iterSrc.value(); + if (offset < srcPat->size()) { + srcPat->removeAt(offset); } } - } -void FunctionalBlock::clearConsumptionPattern() { - if (consumptionPattern == NULL) return; - - for(int i=0;i *> &pattern, int offset) { + QMapIterator* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList* srcPat = iterSrc.value(); + if (offset < srcPat->size()) { + srcPat->insert(offset,0); + } } - delete [] consumptionPattern; } -void FunctionalBlock::clearProductionPattern() { - if (productionPattern == NULL) return; - for(int i=0;i *> &pattern, int offset) { + QMapIterator* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList* srcPat = iterSrc.value(); + if (offset >= srcPat->size()) return false; + if (srcPat->at(offset) == 1) return true; } - delete [] productionPattern; + return false; } -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()) { - 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; - foreach(char c, in) consumptionPattern[idIface][i++] = c; - idIface += 1; +bool FunctionalBlock::isOnlyXDataGroup(const QMap *> &pattern, int offset) { + QMapIterator* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList* srcPat = iterSrc.value(); + if (offset >= srcPat->size()) return false; + if (srcPat->at(offset) != -1) return false; } + return true; } -void FunctionalBlock::initProductionPattern() { - static QString fctName = "FunctionalBlock::initProductionPattern()"; -#ifdef DEBUG_FCTNAME - cout << "call to " << qPrintable(fctName) << endl; -#endif - - if (productionPattern != NULL) clearProductionPattern(); +void FunctionalBlock::clearConsumptionPattern() { + QMapIterator* > iterP(consumptionPattern); + while (iterP.hasNext()) { + iterP.next(); + QList* pattern = iterP.value(); + if (pattern != NULL) delete pattern; + } + consumptionPattern.clear(); + lengthCP = -1; +} + +void FunctionalBlock::clearProductionPattern() { + QMapIterator* > iterP(productionPattern); + while (iterP.hasNext()) { + iterP.next(); + QList* pattern = iterP.value(); + if (pattern != NULL) delete pattern; + } + productionPattern.clear(); + lengthPP = -1; +} + +void FunctionalBlock::clearInputPattern() { - nbProducingPorts = getControlOutputs().size(); - int idIface = 0; - productionPattern = new char*[nbProducingPorts]; - foreach(AbstractInterface* iface, getControlOutputs()) { - 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; - foreach(char c, in) productionPattern[idIface][i++] = c; - idIface += 1; + QMapIterator* > iterI(inputPattern); + while (iterI.hasNext()) { + iterI.next(); + QList* pattern = iterI.value(); + if (pattern != NULL) delete pattern; } + inputPattern.clear(); + lengthIP = -1; +} + +int FunctionalBlock::getNumberOfExecution() { + /* NB: this method returns the number of executions that have been started + but not necessary completed. + */ + if (delta <= 0) return 0; + int nbExec = 0; + int offset = 0; + // search for the first exec. + while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++; + if (offset == lengthIP) return 0; + nbExec = 1; + int nbGroup = 0; + for(int i = offset;i