1 #include "FunctionalBlock.h"
\r
2 #include "ReferenceBlock.h"
\r
3 #include "GroupBlock.h"
\r
4 #include "AbstractInterface.h"
\r
5 #include "FunctionalInterface.h"
\r
6 #include "ReferenceInterface.h"
\r
7 #include "BlockParameter.h"
\r
8 #include "ArithmeticEvaluator.h"
\r
11 FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) : AbstractBlock() {
\r
12 //if (! _reference->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
\r
13 //if (! _group->isGroupBlock()) throw(Exception(BLOCK_INVALID_TYPE));
\r
14 reference = _reference;
\r
16 name = reference->getName();
\r
18 if (reference->getImplementations().isEmpty()) {
\r
19 implementation = NULL;
\r
20 cout << "block has no implementation" << endl;
\r
23 implementation = reference->getImplementations().at(0);
\r
34 FunctionalBlock::~FunctionalBlock() {
\r
35 if (evaluator != NULL) delete evaluator;
\r
38 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
\r
40 checkedBlocks->append(this);
\r
42 foreach(BlockParameter* param, params){
\r
43 if(param->isUserParameter() && !param->isValueSet()){
\r
44 if(!blocksToConfigure->contains(param->getOwner())){
\r
45 blocksToConfigure->append(param->getOwner());
\r
49 foreach(AbstractInterface *inter, outputs){
\r
50 foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
\r
51 if(!checkedBlocks->contains(connectedInter->getOwner())){
\r
52 connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
\r
59 bool FunctionalBlock::isFunctionalBlock() {
\r
63 bool FunctionalBlock::isSourceBlock() {
\r
64 if (parent == NULL) return true;
\r
68 void FunctionalBlock::populate() {
\r
71 AbstractInterface* inter;
\r
73 // create parameters from reference block
\r
74 QList<BlockParameter*> lstParam = reference->getParameters();
\r
75 for(i=0;i<lstParam.size();i++) {
\r
76 p = lstParam.at(i)->clone();
\r
80 // create interfaces from reference block
\r
81 QList<AbstractInterface *> lstRef = reference->getInterfaces();
\r
82 // store relation between functional and reference
\r
83 QHash<AbstractInterface *, AbstractInterface *> hashIface;
\r
84 for(i=0;i<lstRef.size();i++) {
\r
86 inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));
\r
88 catch(Exception e) {
\r
89 cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;
\r
92 hashIface.insert(lstRef.at(i),inter);
\r
94 addInterface(inter);
\r
97 AbstractInterface* funCtlIface = NULL;
\r
98 AbstractInterface* funDataIface = NULL;
\r
100 for(i=0;i<lstRef.size();i++) {
\r
101 AbstractInterface* refIface = lstRef.at(i);
\r
102 if (refIface->getPurpose() == AbstractInterface::Control) {
\r
103 funCtlIface = hashIface.value(refIface);
\r
104 funDataIface = hashIface.value(refIface->getAssociatedIface());
\r
105 if (! funCtlIface->setAssociatedIface(funDataIface)) {
\r
106 cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;
\r
114 QString FunctionalBlock::getReferenceXmlFile() {
\r
115 return ((ReferenceBlock *)reference)->getXmlFile();
\r
118 QString FunctionalBlock::getReferenceHashMd5() {
\r
119 return ((ReferenceBlock *)reference)->getHashMd5();
\r
122 void FunctionalBlock::createPatterns() throw(Exception) {
\r
123 static QString fctName = "FunctionalBlock::createPatterns()";
\r
124 #ifdef DEBUG_FCTNAME
\r
125 cout << "call to " << qPrintable(fctName) << endl;
\r
128 cout << "create patterns for block " << qPrintable(name) << endl;
\r
129 if (evaluator == NULL) evaluator = new ArithmeticEvaluator();
\r
130 if (! isGeneratorBlock()) {
\r
133 createConsumptionPattern();
\r
134 createProductionCounter();
\r
136 catch(Exception e) {
\r
137 throw(e); // rethrow e
\r
141 createProductionPattern();
\r
143 catch(Exception e) {
\r
146 cout << "PP of " << qPrintable(name) << endl;
\r
147 QMapIterator<AbstractInterface*,QList<char>* > it(productionPattern);
\r
148 while (it.hasNext()) {
\r
150 QList<char>* pat = it.value();
\r
151 foreach(char c, *pat) cout << (int)c;
\r
156 void FunctionalBlock::createDelta() throw(Exception) {
\r
157 static QString fctName = "FunctionalBlock::createDelta()";
\r
158 #ifdef DEBUG_FCTNAME
\r
159 cout << "call to " << qPrintable(fctName) << endl;
\r
162 QString deltaStr = implementation->getDelta();
\r
163 cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;
\r
164 if (deltaStr.isEmpty()) {
\r
169 // look for parameter names
\r
172 result = evaluateExpression(deltaStr);
\r
174 catch(Exception e) {
\r
178 cout << "delta = " << delta << endl;
\r
181 void FunctionalBlock::createConsumptionPattern() throw(Exception) {
\r
182 static QString fctName = "FunctionalBlock::createConsumptionPattern()";
\r
183 #ifdef DEBUG_FCTNAME
\r
184 cout << "call to " << qPrintable(fctName) << endl;
\r
188 QHash<QString,QString> consPattern = implementation->getConsumptionPattern();
\r
190 foreach(AbstractInterface* iface, getControlInputs()) {
\r
191 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
192 QString refName = connIface->getReference()->getName();
\r
193 if (! consPattern.contains(refName)) {
\r
194 throw(Exception(NO_IFACE_CP));
\r
195 cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;
\r
197 QList<char>* pattern = NULL;
\r
199 pattern = expandPattern(consPattern.value(refName));
\r
201 catch(Exception e) {
\r
204 consumptionPattern.insert(connIface,pattern);
\r
205 if (lengthCP == -1) {
\r
206 lengthCP = pattern->size();
\r
209 if (pattern->size() != lengthCP) {
\r
210 throw(Exception(INVALID_IFACE_CP_LENGTH));
\r
216 void FunctionalBlock::createProductionPattern() throw(Exception){
\r
217 static QString fctName = "FunctionalBlock::createProductionPattern()";
\r
218 #ifdef DEBUG_FCTNAME
\r
219 cout << "call to " << qPrintable(fctName) << endl;
\r
223 QHash<QString,QString> prodPattern = implementation->getProductionPattern();
\r
225 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
226 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
227 QString refName = connIface->getReference()->getName();
\r
228 if (! prodPattern.contains(refName)) {
\r
229 throw(Exception(NO_IFACE_PP));
\r
231 QList<char>* pattern = NULL;
\r
233 pattern = expandPattern(prodPattern.value(refName));
\r
235 catch(Exception e) {
\r
238 productionPattern.insert(connIface,pattern);
\r
239 if (lengthPP == -1) {
\r
240 lengthPP = pattern->size();
\r
243 if (pattern->size() != lengthPP) {
\r
244 throw(Exception(INVALID_IFACE_PP_LENGTH));
\r
250 void FunctionalBlock::createProductionCounter() throw(Exception) {
\r
251 static QString fctName = "FunctionalBlock::createProductionCounter()";
\r
252 #ifdef DEBUG_FCTNAME
\r
253 cout << "call to " << qPrintable(fctName) << endl;
\r
256 QStringList counterParts = implementation->getProductionCounter().split(",");
\r
257 foreach(QString s, counterParts) {
\r
258 cout << "cont part = " << qPrintable(s) << endl;
\r
260 double val = s.toDouble(&ok);
\r
262 productionCounter.append(val);
\r
264 else if (s.at(0) == '{') {
\r
267 QStringList gen = s.split(":");
\r
268 if (gen.size() != 3) {
\r
269 throw(Exception(INVALID_IFACE_PC));
\r
274 for(int i=0;i<3;i++) {
\r
275 double result = 0.0;
\r
277 result = evaluateExpression(gen.at(i));
\r
279 catch(Exception e) {
\r
282 if (i==0) start = result;
\r
283 else if (i==1) nb = result;
\r
284 else if (i==2) step = result;
\r
286 for(int j=0;j<nb;j++) {
\r
287 productionCounter.append(start+j*step);
\r
291 double result = 0.0;
\r
293 result = evaluateExpression(s);
\r
295 catch(Exception e) {
\r
298 productionCounter.append(result);
\r
301 foreach(int val, productionCounter) {
\r
302 cout << val << ",";
\r
307 QList<char>* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exception) {
\r
308 static QString fctName = "FunctionalBlock::expandPattern()";
\r
309 #ifdef DEBUG_FCTNAME
\r
310 cout << "call to " << qPrintable(fctName) << endl;
\r
314 QString p = patternIn;
\r
317 QList<char>* patternOut = new QList<char>();
\r
319 patternOut->append(expandPatternRecur(p,&offset));
\r
321 catch(Exception e) {
\r
328 QList<char> FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset) throw(Exception) {
\r
330 QList<char> patternOut;
\r
332 while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) {
\r
334 QChar c = patternIn.at(*offset);
\r
338 patternOut.append(expandPatternRecur(patternIn,offset));
\r
340 catch(Exception e) {
\r
344 else if (c == '0') {
\r
345 patternOut.append(0);
\r
347 else if (c == '1') {
\r
348 patternOut.append(1);
\r
350 else if (c == 'X') {
\r
351 patternOut.append(-1);
\r
353 else if (c == '{') {
\r
355 QString expr = "";
\r
356 while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {
\r
357 expr += patternIn.at(*offset);
\r
360 if (*offset == patternIn.size()) {
\r
361 throw(Exception(INVALID_IFACE_PATTERN));
\r
365 repeat = evaluateExpression(expr);
\r
367 catch(Exception e) {
\r
370 // repeat just the last value in currentGroup
\r
371 char last = patternOut.last();
\r
372 //cout << "repeat last char " << repeat << " times : " << (int)last << endl;
\r
374 for(int i=1;i<(int)repeat;i++) {
\r
375 patternOut.append(last);
\r
381 // must check if after ), there is a {
\r
382 if ((*offset < patternIn.size()-1) && (patternIn.at(*offset+1) == '{')) {
\r
384 QString expr = "";
\r
385 while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {
\r
386 expr += patternIn.at(*offset);
\r
389 if (*offset == patternIn.size()) {
\r
390 throw(Exception(INVALID_IFACE_PATTERN));
\r
394 repeat = evaluateExpression(expr);
\r
396 catch(Exception e) {
\r
400 cout << "repeat last group " << repeat << " times : ";
\r
401 foreach (char c, currentGroup) cout <<(int)c;
\r
404 QList<char> single = patternOut;
\r
405 for(int i=1;i<(int)repeat;i++) {
\r
406 patternOut.append(single);
\r
412 double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exception) {
\r
413 static QString fctName = "FunctionalBlock::evaluateExpression()";
\r
414 #ifdef DEBUG_FCTNAME
\r
415 cout << "call to " << qPrintable(fctName) << endl;
\r
418 QHash<QString,double> vars;
\r
419 evaluator->setExpression(expression);
\r
420 QList<QString> varNames = evaluator->getVariableNames();
\r
421 foreach (QString name, varNames) {
\r
422 QString paramName = name;
\r
423 paramName.remove(0,1);
\r
424 BlockParameter* param = reference->getParameterFromName(paramName);
\r
425 if (param == NULL) {
\r
426 throw(Exception(EVAL_PARAM_UNKNOWN));
\r
429 int val = param->getDoubleValue(&okVal);
\r
431 throw(Exception(EVAL_PARAM_NOVALUE));
\r
433 vars.insert(name,(double)val);
\r
436 evaluator->setVariablesValue(vars);
\r
437 double result = 0.0;
\r
439 result = evaluator->evaluate();
\r
442 cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;
\r
443 throw(Exception(EVAL_INVALID_EXPR));
\r
448 void FunctionalBlock::createInputPattern() throw(Exception) {
\r
449 static QString fctName = "FunctionalBlock::createInputPattern())";
\r
450 #ifdef DEBUG_FCTNAME
\r
451 cout << "call to " << qPrintable(fctName) << endl;
\r
455 foreach(AbstractInterface* iface, getControlInputs()) {
\r
456 ConnectedInterface* connIface = AI_TO_CON(iface);
\r
457 QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
\r
458 if (out->size() == 0) {
\r
459 clearInputPattern();
\r
460 throw(Exception(NO_IFACE_IP));
\r
462 if (lengthIP == -1) {
\r
463 lengthIP = out->size();
\r
466 if (out->size() < lengthIP) lengthIP = out->size();
\r
469 QList<char>* in = new QList<char>(*out);
\r
470 foreach(char c, *in) {
\r
474 inputPattern.insert(connIface,in);
\r
476 // search the last valid group in IP,
\r
477 while(! isValidDataGroup(inputPattern,lengthIP-1)) {
\r
478 //removeDataGroup(inputPattern,lengthIP-1);
\r
483 void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) {
\r
484 static QString fctName = "FunctionalBlock::createAdmittance()";
\r
485 #ifdef DEBUG_FCTNAME
\r
486 cout << "call to " << qPrintable(fctName) << endl;
\r
488 // firstly, copy CP in AP
\r
489 QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);
\r
490 while (iterC.hasNext()) {
\r
492 QList<char>* pattern = new QList<char>(*(iterC.value()));
\r
493 admittance.insert(iterC.key(), pattern);
\r
495 lengthAP = lengthCP;
\r
497 cout << "trigger 1 at c.c. 0" << endl;
\r
498 for(int i=1;i<nbExec;i++) {
\r
499 // searching for the clock cycle for which a new exec starts
\r
501 while ((clock < lengthAP) && (nbGroup < delta)) {
\r
502 if (isValidDataGroup(admittance,clock)) nbGroup+=1;
\r
505 while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;
\r
506 cout << "trigger " << (i+1) << " at c.c. " << clock << endl;
\r
508 // combine CP with AP at sc
\r
509 for(int j=0;j<lengthCP;j++) {
\r
510 // first case : column of CP must be placed beyond AP's end.
\r
511 if (sc == lengthAP) {
\r
512 cout << i << "," << j << " append in AP at " << sc << endl;
\r
513 appendToPattern(consumptionPattern,j,admittance,1);
\r
517 // second case : CP and AP can be combined directly (i.e. no X | 1 to do)
\r
518 else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {
\r
519 cout << i << "," << j << " combine at " << sc << endl;
\r
520 combinePatterns(consumptionPattern,j,admittance,sc);
\r
523 // third case : CP has an X column
\r
524 else if (isOnlyXDataGroup(consumptionPattern,j)) {
\r
525 cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;
\r
526 shiftRightPattern(admittance,sc);
\r
528 if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {
\r
529 cerr << "Abnormal case when combining AP and CP" << endl;
\r
531 combinePatterns(consumptionPattern,j,admittance,sc);
\r
534 // fourth case : AP has an X column
\r
535 else if (isOnlyXDataGroup(admittance,sc)) {
\r
536 cout << i << "," << j << " jump c.c. for CP at " << sc << endl;
\r
541 throw(INVALID_DELTA_CP);
\r
545 // turn all X into 0
\r
546 QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);
\r
547 while (iterA.hasNext()) {
\r
549 QList<char>* pattern = iterA.value();
\r
550 for(int i=0;i<pattern->size();i++) {
\r
551 if (pattern->at(i) == -1) pattern->replace(i,0);
\r
552 cout << (int)(pattern->at(i));
\r
558 void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) {
\r
559 static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";
\r
560 #ifdef DEBUG_FCTNAME
\r
561 cout << "call to " << qPrintable(fctName) << endl;
\r
564 // firstly, create input pattern
\r
566 createInputPattern();
\r
568 catch(Exception e) {
\r
571 int nbExec = createTriggers();
\r
572 cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;
\r
575 createAdmittance(nbExec);
\r
577 catch(Exception e) {
\r
578 cout << "cannot create admittance" << endl;
\r
582 int clock = 0; // index in IP
\r
583 int i = 0; // index in AP
\r
584 while ((clock < lengthIP) && (i < lengthAP)) {
\r
586 // if AP is a valid group, search for the next valid group in IP
\r
587 if (isValidDataGroup(admittance,i)) {
\r
588 while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;
\r
589 if (clock == lengthIP) {
\r
590 cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;
\r
591 throw(Exception(IP_END_NULLCOL));
\r
594 /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or
\r
595 are both null columns
\r
597 if (! samePatterns(inputPattern,clock,admittance,i)) {
\r
598 cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;
\r
599 throw(Exception(IP_AP_NOTCOMPAT)); // IP and AP not compatible
\r
604 if (clock < lengthIP) {
\r
605 throw(Exception(AP_TOO_SHORT));
\r
606 cerr << "Abnormal case: AP is to short" << endl;
\r
610 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {
\r
611 static QString fctName = "FunctionalBlock::computeOutputPattern()";
\r
612 #ifdef DEBUG_FCTNAME
\r
613 cout << "call to " << qPrintable(fctName) << endl;
\r
616 /* case 1: the block is a generator for which output pattern
\r
617 must be computed for a nbExec following executions
\r
622 cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;
\r
623 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
624 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
625 // create output pattern
\r
626 QList<char>* pp = productionPattern.value(connIface);
\r
627 QList<char>* pattern = new QList<char>(*pp);
\r
628 for(int i=1;i<nbExec;i++) pattern->append(*pp);
\r
629 // assign pattern to interface
\r
630 connIface->setOutputPattern(pattern);
\r
631 // store it in QMap
\r
632 outputPattern.insert(connIface,pattern);
\r
636 cout << "computing output pattern of " << qPrintable(name) << endl;
\r
638 // in case of inputPattern not created, do it
\r
639 if (lengthIP <= 0) {
\r
640 // collect the input patterns for each input
\r
642 createInputPattern();
\r
644 catch(Exception e) {
\r
647 cout << "input pattern array initialized with min. len " << lengthIP << endl;
\r
650 // initialize the output pattern
\r
652 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
653 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
654 lengthOP = lengthIP+productionPattern.value(connIface)->size();
\r
655 QList<char>* pattern = new QList<char>();
\r
656 for(int i=0;i<lengthOP;i++) pattern->append(0);
\r
657 connIface->setOutputPattern(pattern);
\r
658 outputPattern.insert(connIface,pattern);
\r
660 cout << "output pattern array initialized" << endl;
\r
664 // search for the beginning of the first execution.
\r
665 while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;
\r
666 cout << "found 1st exec clock: " << clock << endl;
\r
668 while (clock < lengthIP) {
\r
669 // initialize counters for current execution.
\r
670 int p = 0; // index in production pattern
\r
671 int o = 0; // clock+o will give the clock cycle of each output group
\r
672 int cip = 0; // clock+cip give the clock cycle of an input group
\r
673 int ccp = 0; // ccp give a column in the consumptio pattern
\r
674 int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP
\r
675 int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP
\r
676 bool cannotCompleteExec = false;
\r
677 for(int m=0;m<productionCounter.size();m++) {
\r
678 // search for the first production in PP
\r
679 while (!isValidDataGroup(productionPattern,p)) {
\r
683 int gap = 0; // count the number of extra null columns
\r
684 // search for PC(m) valid input group in IP
\r
685 while (nip < productionCounter.at(m)) {
\r
686 if (clock+cip < lengthIP) {
\r
687 if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;
\r
692 cannotCompleteExec = true;
\r
697 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
699 // search for PC(m) valid input group in IP
\r
700 while (ncp < productionCounter.at(m)) {
\r
701 if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;
\r
705 o += gap; // to take into acocunt of extra null columns
\r
706 combinePatterns(productionPattern,p,outputPattern,clock+o);
\r
711 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
713 // current exec. taken into accunt
\r
716 // search for the next exec.
\r
719 while ((clock < lengthIP) && (nip < delta)) {
\r
720 if (isValidDataGroup(inputPattern,clock)) nip += 1;
\r
721 if (nip < delta) clock += 1;
\r
723 cout << "found exec " << nbExec << " at clock: " << clock << endl;
\r
725 // find the last valid output data group
\r
726 while(! isValidDataGroup(outputPattern,lengthOP-1)) {
\r
727 removeDataGroup(outputPattern,lengthOP-1);
\r
731 // clear input pattern
\r
732 clearInputPattern();
\r
738 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {
\r
739 static QString fctName = "FunctionalBlock::computeOutputPattern()";
\r
740 #ifdef DEBUG_FCTNAME
\r
741 cout << "call to " << qPrintable(fctName) << endl;
\r
744 // case 1: the block is a generator for which output pattern
\r
745 // must be computed for a nbExec following executions
\r
748 cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;
\r
749 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
750 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
751 // create output pattern
\r
752 QList<char>* pp = productionPattern.value(connIface);
\r
753 QList<char>* pattern = new QList<char>(*pp);
\r
754 for(int i=1;i<nbExec;i++) pattern->append(*pp);
\r
755 // assign pattern to interface
\r
756 connIface->setOutputPattern(pattern);
\r
757 // store it in QMap
\r
758 outputPattern.insert(connIface,pattern);
\r
762 cout << "computing output pattern of " << qPrintable(name) << endl;
\r
764 // in case of inputPattern not created, do it
\r
765 if (lengthIP <= 0) {
\r
766 // collect the input patterns for each input
\r
768 createInputPattern();
\r
770 catch(Exception e) {
\r
773 cout << "input pattern array initialized with min. len " << lengthIP << endl;
\r
776 // initialize the output pattern
\r
778 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
779 FunctionalInterface* connIface = AI_TO_FUN(iface);
\r
780 lengthOP = lengthIP+productionPattern.value(connIface)->size();
\r
781 QList<char>* pattern = new QList<char>();
\r
782 for(int i=0;i<lengthOP;i++) pattern->append(0);
\r
783 connIface->setOutputPattern(pattern);
\r
784 outputPattern.insert(connIface,pattern);
\r
786 cout << "output pattern array initialized" << endl;
\r
790 // search for the beginning of the first execution.
\r
791 while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;
\r
792 cout << "found 1st exec clock: " << clock << endl;
\r
794 while (clock < lengthIP) {
\r
795 // initialize counters for current execution.
\r
796 int p = 0; // index in production pattern
\r
797 int o = 0; // clock+o will give the clock cycle of each output group
\r
798 int cip = 0; // clock+cip give the clock cycle of an input group
\r
799 int ccp = 0; // ccp give a column in the consumptio pattern
\r
800 int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP
\r
801 int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP
\r
802 bool cannotCompleteExec = false;
\r
803 for(int m=0;m<productionCounter.size();m++) {
\r
804 // search for the first production in PP
\r
805 while (!isValidDataGroup(productionPattern,p)) {
\r
809 int gap = 0; // count the number of extra null columns
\r
810 // search for PC(m) valid input group in IP
\r
811 while (nip < productionCounter.at(m)) {
\r
812 if (clock+cip < lengthIP) {
\r
813 if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;
\r
818 cannotCompleteExec = true;
\r
823 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
825 // search for PC(m) valid input group in IP
\r
826 while (ncp < productionCounter.at(m)) {
\r
827 if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;
\r
831 o += gap; // to take into acocunt of extra null columns
\r
832 combinePatterns(productionPattern,p,outputPattern,clock+o);
\r
837 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
839 // current exec. taken into accunt
\r
842 // search for the next exec.
\r
845 while ((clock < lengthIP) && (nip < delta)) {
\r
846 if (isValidDataGroup(inputPattern,clock)) nip += 1;
\r
847 if (nip < delta) clock += 1;
\r
849 cout << "found exec " << nbExec << " at clock: " << clock << endl;
\r
851 // find the last valid output data group
\r
852 while(! isValidDataGroup(outputPattern,lengthOP-1)) {
\r
853 removeDataGroup(outputPattern,lengthOP-1);
\r
857 // clear input pattern
\r
858 clearInputPattern();
\r
862 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {
\r
864 if (patternSrc.size() != patternDest.size()) return false;
\r
865 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
\r
866 QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
\r
867 while (iterSrc.hasNext()) {
\r
870 QList<char>* srcPat = iterSrc.value();
\r
871 QList<char>* destPat = iterDest.value();
\r
872 if (srcCol >= srcPat->size()) return false;
\r
873 if (destCol >= destPat->size()) return false;
\r
874 if (srcPat->at(srcCol) != destPat->at(destCol)) return false;
\r
879 bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {
\r
880 if (patternSrc.size() != patternDest.size()) return false;
\r
881 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
\r
882 QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
\r
883 while (iterSrc.hasNext()) {
\r
886 QList<char>* srcPat = iterSrc.value();
\r
887 QList<char>* destPat = iterDest.value();
\r
888 if (srcCol >= srcPat->size()) return false;
\r
889 if (destCol >= destPat->size()) return false;
\r
890 if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;
\r
891 if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;
\r
896 void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {
\r
897 if (patternSrc.size() != patternDest.size()) return;
\r
898 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
\r
899 QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
\r
900 while (iterSrc.hasNext()) {
\r
903 QList<char>* srcPat = iterSrc.value();
\r
904 QList<char>* destPat = iterDest.value();
\r
905 if (srcCol >= srcPat->size()) return;
\r
906 if (destCol >= destPat->size()) return;
\r
907 if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;
\r
908 if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;
\r
909 destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));
\r
913 void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {
\r
914 if (patternSrc.size() != patternDest.size()) return;
\r
915 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
\r
916 QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
\r
917 while (iterSrc.hasNext()) {
\r
920 QList<char>* srcPat = iterSrc.value();
\r
921 QList<char>* destPat = iterDest.value();
\r
923 while ((srcCol+i < srcPat->size()) && (i<nbCols)) {
\r
924 destPat->append(srcPat->at(srcCol+i));
\r
930 void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
\r
931 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);
\r
932 while (iterSrc.hasNext()) {
\r
934 QList<char>* srcPat = iterSrc.value();
\r
935 if (offset < srcPat->size()) {
\r
936 srcPat->removeAt(offset);
\r
941 void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
\r
942 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);
\r
943 while (iterSrc.hasNext()) {
\r
945 QList<char>* srcPat = iterSrc.value();
\r
946 if (offset < srcPat->size()) {
\r
947 srcPat->insert(offset,0);
\r
952 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
\r
953 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);
\r
954 while (iterSrc.hasNext()) {
\r
956 QList<char>* srcPat = iterSrc.value();
\r
957 if (offset >= srcPat->size()) return false;
\r
958 if (srcPat->at(offset) == 1) return true;
\r
963 bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
\r
964 QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);
\r
965 while (iterSrc.hasNext()) {
\r
967 QList<char>* srcPat = iterSrc.value();
\r
968 if (offset >= srcPat->size()) return false;
\r
969 if (srcPat->at(offset) != -1) return false;
\r
974 void FunctionalBlock::clearConsumptionPattern() {
\r
975 QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);
\r
976 while (iterP.hasNext()) {
\r
978 QList<char>* pattern = iterP.value();
\r
979 if (pattern != NULL) delete pattern;
\r
981 consumptionPattern.clear();
\r
985 void FunctionalBlock::clearProductionPattern() {
\r
986 QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);
\r
987 while (iterP.hasNext()) {
\r
989 QList<char>* pattern = iterP.value();
\r
990 if (pattern != NULL) delete pattern;
\r
992 productionPattern.clear();
\r
996 void FunctionalBlock::clearInputPattern() {
\r
998 QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);
\r
999 while (iterI.hasNext()) {
\r
1001 QList<char>* pattern = iterI.value();
\r
1002 if (pattern != NULL) delete pattern;
\r
1004 inputPattern.clear();
\r
1008 int FunctionalBlock::createTriggers() {
\r
1010 /* NB: this method returns the number of executions that have been started
\r
1011 but not necessary completed.
\r
1013 if (delta <= 0) return 0;
\r
1015 // search for the first exec.
\r
1016 while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;
\r
1017 if (offset == lengthIP) return 0;
\r
1018 triggers.append(offset);
\r
1020 for(int i = offset;i<lengthIP;i++) {
\r
1021 if (isValidDataGroup(inputPattern,i)) nbGroup++;
\r
1022 if (nbGroup == delta+1) {
\r
1023 triggers.append(i);
\r
1027 return triggers.size();
\r