From 2019e5afdaf7fd0ad21607848710348bbc3be256 Mon Sep 17 00:00:00 2001 From: stephane Domas <stephane.domas@univ-fcomte.fr> Date: Fri, 19 May 2017 16:41:28 +0200 Subject: [PATCH 1/1] added admittance computation --- FunctionalBlock.cpp | 261 ++++++++++++++++----- FunctionalBlock.h | 20 +- Graph.cpp | 10 +- blast.creator.user | 2 +- lib/implementations/generator-cst_impl.xml | 4 +- 5 files changed, 231 insertions(+), 66 deletions(-) diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 23d43b9..ac27de4 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -117,10 +117,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(); @@ -134,8 +134,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; @@ -154,6 +158,7 @@ bool FunctionalBlock::createConsumptionPattern() { cout << "call to " << qPrintable(fctName) << endl; #endif + lengthCP = -1; bool ok = true; QHash<QString,QString> consPattern = implementation->getConsumptionPattern(); @@ -164,10 +169,15 @@ bool FunctionalBlock::createConsumptionPattern() { cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl; return false; } - QList<char>* pattern = expandPattern(consPattern.value(refName),&ok); - + QList<char>* pattern = expandPattern(consPattern.value(refName),&ok); if (!ok) return false; - consumptionPattern.insert(connIface,pattern); + consumptionPattern.insert(connIface,pattern); + if (lengthCP == -1) { + lengthCP = pattern->size(); + } + else { + if (pattern->size() != lengthCP) return false; + } } return true; } @@ -178,6 +188,7 @@ bool FunctionalBlock::createProductionPattern() { cout << "call to " << qPrintable(fctName) << endl; #endif + lengthPP = -1; bool ok = true; QHash<QString,QString> prodPattern = implementation->getProductionPattern(); @@ -190,7 +201,13 @@ bool FunctionalBlock::createProductionPattern() { } QList<char>* pattern = expandPattern(prodPattern.value(refName),&ok); if (!ok) return false; - productionPattern.insert(connIface,pattern); + productionPattern.insert(connIface,pattern); + if (lengthPP == -1) { + lengthPP = pattern->size(); + } + else { + if (pattern->size() != lengthPP) return false; + } } return true; } @@ -379,6 +396,121 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) return result; } +void FunctionalBlock::createInputPattern() { + lengthIP = -1; + foreach(AbstractInterface* iface, getControlInputs()) { + ConnectedInterface* connIface = AI_TO_CON(iface); + QList<char>* out = connIface->getConnectedFrom()->getOutputPattern(); + if (lengthIP == -1) { + lengthIP = out->size(); + } + else { + if (out->size() < lengthIP) lengthIP = out->size(); + } + if (out->size() > 0) { + QList<char>* in = new QList<char>(*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<AbstractInterface*,QList<char>* > iterC(consumptionPattern); + while (iterC.hasNext()) { + iterC.next(); + QList<char>* pattern = new QList<char>(*(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<nbExec;i++) { + // searching for the clock cycle for which a new exec starts + int nbGroup = 0; + while ((clock < lengthAP) && (nbGroup < delta)) { + if (isValidDataGroup(admittance,clock)) nbGroup+=1; + clock += 1; + } + while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1; + cout << "trigger " << (i+1) << " at c.c. " << clock << endl; + int sc = clock; + // combine CP with AP at sc + for(int j=0;j<lengthCP;j++) { + // first case : column of CP must be placed beyond AP's end. + if (sc == lengthAP) { + cout << i << "," << j << " append in AP at " << sc << endl; + appendToPattern(consumptionPattern,j,admittance,1); + lengthAP += 1; + sc += 1; + } + // second case : CP and AP can be combined directly (i.e. no X | 1 to do) + else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) { + cout << i << "," << j << " combine at " << sc << endl; + combinePatterns(consumptionPattern,j,admittance,sc); + sc += 1; + } + // third case : CP has an X column + else if (isOnlyXDataGroup(consumptionPattern,j)) { + cout << i << "," << j << " shift rigth AP to combine at " << sc << endl; + shiftRightPattern(admittance,sc); + lengthAP += 1; + if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) { + cerr << "Abnormal case when combining AP and CP" << endl; + } + combinePatterns(consumptionPattern,j,admittance,sc); + sc += 1; + } + // fourth case : AP has an X column + else if (isOnlyXDataGroup(admittance,sc)) { + cout << i << "," << j << " jump c.c. for CP at " << sc << endl; + sc += 1; + j -= 1; + } + else { + cout << "AP and CP are not consistent" << endl; + return false; + } + } + } + + 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; + + return true; +} + bool FunctionalBlock::computeOutputPattern(int nbExec) { static QString fctName = "FunctionalBlock::computeOutputPattern()"; #ifdef DEBUG_FCTNAME @@ -407,48 +539,23 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { else { cout << "computing output pattern of " << qPrintable(name) << endl; - // collect the input patterns for each input - QMap<AbstractInterface*,QList<char>* > inputPattern; - int minLen = -1; - foreach(AbstractInterface* iface, getControlInputs()) { - ConnectedInterface* connIface = AI_TO_CON(iface); - QList<char>* out = connIface->getConnectedFrom()->getOutputPattern(); - if (minLen == -1) { - minLen = out->size(); - } - else { - if (out->size() < minLen) minLen = out->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; } - if (out->size() > 0) { - QList<char>* in = new QList<char>(*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<AbstractInterface*,QList<char>* > iterI(inputPattern); - while (iterI.hasNext()) { - iterI.next(); - QList<char>* pattern = iterI.value(); - if (pattern != NULL) delete pattern; - } - return false; + cout << "input pattern array initialized with min. len " << lengthIP << endl; } - cout << "input pattern array initialized with min. len " << minLen << 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<char>* pattern = new QList<char>(); for(int i=0;i<lengthOP;i++) pattern->append(0); connIface->setOutputPattern(pattern); @@ -459,10 +566,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 +587,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 +620,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 +632,8 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) { lengthOP -= 1; } - // clear input pattern - QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern); - while (iterI.hasNext()) { - iterI.next(); - QList<char>* pattern = iterI.value(); - if (pattern != NULL) delete pattern; - } + // clear input pattern + clearInputPattern(); } return true; } @@ -598,6 +700,17 @@ void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> & } } +void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) { + QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern); + while (iterSrc.hasNext()) { + iterSrc.next(); + QList<char>* srcPat = iterSrc.value(); + if (offset < srcPat->size()) { + srcPat->insert(offset,0); + } + } +} + bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) { QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern); while (iterSrc.hasNext()) { @@ -627,6 +740,8 @@ void FunctionalBlock::clearConsumptionPattern() { QList<char>* pattern = iterP.value(); if (pattern != NULL) delete pattern; } + consumptionPattern.clear(); + lengthCP = -1; } void FunctionalBlock::clearProductionPattern() { @@ -636,4 +751,40 @@ void FunctionalBlock::clearProductionPattern() { QList<char>* pattern = iterP.value(); if (pattern != NULL) delete pattern; } + productionPattern.clear(); + lengthPP = -1; } + +void FunctionalBlock::clearInputPattern() { + + QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern); + while (iterI.hasNext()) { + iterI.next(); + QList<char>* 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<lengthIP;i++) { + if (isValidDataGroup(inputPattern,offset)) nbGroup++; + if (nbGroup == delta+1) { + nbExec += 1; + nbGroup = 1; + } + } + return nbExec; +} diff --git a/FunctionalBlock.h b/FunctionalBlock.h index 2cf9a5a..6f47a00 100644 --- a/FunctionalBlock.h +++ b/FunctionalBlock.h @@ -31,6 +31,10 @@ public: // getters inline ReferenceBlock* getReference() { return reference; } inline QList<int> getProductionCounter() { return productionCounter; } + inline QMap<AbstractInterface*, QList<char>* > getConsumptionPattern() { return consumptionPattern; } + inline QMap<AbstractInterface*, QList<char>* > getProductionPattern() { return productionPattern; } + inline int getConsumptionPatternLength() { return lengthCP; } + inline int getProductionPatternLength() { return lengthPP; } inline int getDelta() { return delta; } // setters @@ -57,8 +61,13 @@ public: bool createConsumptionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation bool createProductionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation bool createProductionCounter(); // initialize a QList<int> from counter defined in implementation + bool createAdmittance(int nbExec); // initialize a QList<char> from consumption pattern and delta void clearConsumptionPattern(); void clearProductionPattern(); + void createInputPattern(); + void clearInputPattern(); + int getNumberOfExecution(); // compute number of block execution from inputPattern and delta + bool checkInputPatternCompatibility(); bool computeOutputPattern(int nbExec = -1); private: @@ -126,12 +135,17 @@ private: void shiftRightPattern(const QMap<AbstractInterface*, QList<char>* >& pattern, int offset); QMap<AbstractInterface*, QList<char>* > consumptionPattern; - QMap<AbstractInterface*, QString > admittance; // the admittance expressed as prologue-cyclic part-eppilogue - QMap<AbstractInterface*, QList<char>* > admittanceExpanded; // the admittance expanded by taking into account nb exec. + QMap<AbstractInterface*, QString > admittanceCyclic; // the admittance expressed as prologue-cyclic part-eppilogue, deduced from admittance + QMap<AbstractInterface*, QList<char>* > admittance; // the admittance taking into account nb exec. QMap<AbstractInterface*, QList<char>* > productionPattern; + QMap<AbstractInterface*,QList<char>* > inputPattern; QMap<AbstractInterface*, QList<char>* > outputPattern; // CAUTION: the QList<char>* must also be stored in the outputPattern attributes of AbstractInterface QList<int> productionCounter; //! only usefull for control output interfaces - + int lengthIP; // for convenience, set in createInputPattern() + int lengthCP; // for convenience, set in createConsumptionPattern() + int lengthAP; // for convenience, set in createAdmittance() + int lengthPP; // for convenience, set in createProductionPattern() + int lengthOP; // for convenience, set in computeOutputPattern() int delta; ArithmeticEvaluator* evaluator; diff --git a/Graph.cpp b/Graph.cpp index 999e72a..eb66dc4 100644 --- a/Graph.cpp +++ b/Graph.cpp @@ -158,15 +158,15 @@ bool Graph::computeOutputPatterns(int nbExec) { } } } - // search for maximum delta - int maxDelta = 0; + // search for maximum PP length + int maxPP = 0; foreach(FunctionalBlock* block, generators) { - if (block->getDelta() > maxDelta) maxDelta = block->getDelta(); + if (block->getProductionPatternLength() > maxPP) maxPP = block->getProductionPatternLength(); } // compute output for generators - int maxExecLen = maxDelta*nbExec; + int maxExecLen = maxPP*nbExec; foreach(FunctionalBlock* block, generators) { - int d = block->getDelta(); + int d = block->getProductionPatternLength(); block->computeOutputPattern((maxExecLen+d-1)/d); } // compute output for top group diff --git a/blast.creator.user b/blast.creator.user index dc3af4e..acd48e9 100755 --- a/blast.creator.user +++ b/blast.creator.user @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE QtCreatorProject> -<!-- Written by QtCreator 3.2.1, 2017-05-18T16:26:09. --> +<!-- Written by QtCreator 3.2.1, 2017-05-19T16:37:01. --> <qtcreator> <data> <variable>EnvironmentId</variable> diff --git a/lib/implementations/generator-cst_impl.xml b/lib/implementations/generator-cst_impl.xml index 0c94e16..9768641 100644 --- a/lib/implementations/generator-cst_impl.xml +++ b/lib/implementations/generator-cst_impl.xml @@ -24,11 +24,11 @@ </architecture> <patterns> - <delta value="$seq_length+$idle_length" /> + <delta value="$seq_length" /> <consumption> </consumption> <production counter=""> - <output name="data_o_enb" pattern="1{$seq_length}X{$idle_length}" /> + <output name="data_o_enb" pattern="1{$seq_length}0{$idle_length}" /> </production> </patterns> </block_impl> -- 2.39.5