]> AND Private Git Repository - blast.git/blob - FunctionalBlock.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
7a4d4ff8fa332d391e05e8f03c6e7349ae7de387
[blast.git] / FunctionalBlock.cpp
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
9 \r
10 \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
15   parent = _parent;\r
16   name = reference->getName();\r
17 \r
18   if (reference->getImplementations().isEmpty()) {\r
19     implementation = NULL;\r
20     cout << "block has no implementation" << endl;\r
21   }\r
22   else {\r
23     implementation = reference->getImplementations().at(0);\r
24   }\r
25   lengthAP = -1;\r
26   lengthCP = -1;\r
27   lengthIP = -1;\r
28   lengthOP = -1;\r
29   lengthPP = -1;\r
30   delta = -1;\r
31 }\r
32 \r
33 \r
34 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {\r
35   /*\r
36   checkedBlocks->append(this);\r
37 \r
38   foreach(BlockParameter* param, params){\r
39     if(param->isUserParameter() && !param->isValueSet()){\r
40       if(!blocksToConfigure->contains(param->getOwner())){\r
41         blocksToConfigure->append(param->getOwner());\r
42       }\r
43     }\r
44   }\r
45   foreach(AbstractInterface *inter, outputs){\r
46     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
47       if(!checkedBlocks->contains(connectedInter->getOwner())){\r
48         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
49       }\r
50     }\r
51   }\r
52   */\r
53 }\r
54 \r
55 bool FunctionalBlock::isFunctionalBlock() {\r
56   return true;\r
57 }\r
58 \r
59 bool FunctionalBlock::isSourceBlock() {\r
60   if (parent == NULL) return true;\r
61   return false;\r
62 }\r
63 \r
64 void FunctionalBlock::populate() {\r
65   int i;\r
66   BlockParameter* p;\r
67   AbstractInterface* inter;\r
68 \r
69   // create parameters from reference block\r
70   QList<BlockParameter*> lstParam = reference->getParameters();\r
71   for(i=0;i<lstParam.size();i++) {\r
72     p = lstParam.at(i)->clone();\r
73     addParameter(p);\r
74   }\r
75 \r
76   // create interfaces from reference block\r
77   QList<AbstractInterface *> lstRef = reference->getInterfaces();\r
78   // store relation between functional and reference\r
79   QHash<AbstractInterface *, AbstractInterface *> hashIface;\r
80   for(i=0;i<lstRef.size();i++) {\r
81     try {\r
82       inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));\r
83     }\r
84     catch(Exception e) {\r
85       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
86       exit(1);\r
87     }\r
88     hashIface.insert(lstRef.at(i),inter);\r
89 \r
90     addInterface(inter);\r
91   }\r
92     \r
93   AbstractInterface* funCtlIface = NULL;\r
94   AbstractInterface* funDataIface = NULL;\r
95   \r
96   for(i=0;i<lstRef.size();i++) {    \r
97     AbstractInterface* refIface = lstRef.at(i);    \r
98     if (refIface->getPurpose() == AbstractInterface::Control) {\r
99       funCtlIface = hashIface.value(refIface);\r
100       funDataIface = hashIface.value(refIface->getAssociatedIface());\r
101       if (! funCtlIface->setAssociatedIface(funDataIface)) {\r
102         cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;\r
103         exit(1);\r
104       }       \r
105     }\r
106   }\r
107 }\r
108 \r
109 \r
110 QString FunctionalBlock::getReferenceXmlFile() {\r
111     return ((ReferenceBlock *)reference)->getXmlFile();\r
112 }\r
113 \r
114 QString FunctionalBlock::getReferenceHashMd5() {\r
115     return ((ReferenceBlock *)reference)->getHashMd5();\r
116 }\r
117 \r
118 bool FunctionalBlock::createPatterns() {\r
119   static QString fctName = "FunctionalBlock::createPatterns()";\r
120 #ifdef DEBUG_FCTNAME\r
121   cout << "call to " << qPrintable(fctName) << endl;\r
122 #endif\r
123   \r
124   cout << "create patterns for block " << qPrintable(name) << endl;\r
125   evaluator = new ArithmeticEvaluator();\r
126   bool ok = true;  \r
127   if (! isGeneratorBlock()) {\r
128     ok = ok & createDelta();\r
129     if (ok) ok = ok & createConsumptionPattern();    \r
130     if (ok) ok = ok & createProductionCounter();\r
131   }\r
132   if (ok) ok = ok & createProductionPattern();\r
133   delete evaluator;\r
134   return ok;\r
135 }\r
136 \r
137 bool FunctionalBlock::createDelta() {\r
138   static QString fctName = "FunctionalBlock::createDelta()";\r
139 #ifdef DEBUG_FCTNAME\r
140   cout << "call to " << qPrintable(fctName) << endl;\r
141 #endif \r
142   \r
143   QString deltaStr = implementation->getDelta();  \r
144   cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;\r
145   if (deltaStr.isEmpty()) {\r
146     delta = -1;\r
147     return true;\r
148   }\r
149   \r
150   // look for parameter names\r
151   bool ok = true;\r
152   double result = evaluateExpression(deltaStr, &ok);\r
153   if (!ok) return false;\r
154   \r
155   delta = result;\r
156   cout << "delta = " << delta << endl;\r
157    \r
158   return true;\r
159 }\r
160 \r
161 bool FunctionalBlock::createConsumptionPattern() {\r
162   static QString fctName = "FunctionalBlock::createConsumptionPattern()";\r
163 #ifdef DEBUG_FCTNAME\r
164   cout << "call to " << qPrintable(fctName) << endl;\r
165 #endif\r
166   \r
167   lengthCP = -1;\r
168   bool ok = true; \r
169   QHash<QString,QString> consPattern = implementation->getConsumptionPattern();  \r
170   \r
171   foreach(AbstractInterface* iface, getControlInputs()) {       \r
172     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
173     QString refName = connIface->getReference()->getName();    \r
174     if (! consPattern.contains(refName)) {\r
175       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;\r
176       return false;\r
177     }\r
178     QList<char>* pattern = expandPattern(consPattern.value(refName),&ok);        \r
179     if (!ok) return false;\r
180     consumptionPattern.insert(connIface,pattern);\r
181     if (lengthCP == -1) {\r
182       lengthCP = pattern->size();\r
183     }\r
184     else {\r
185       if (pattern->size() != lengthCP) return false;\r
186     }\r
187   }        \r
188   return true;\r
189 }\r
190 \r
191 bool FunctionalBlock::createProductionPattern() {  \r
192   static QString fctName = "FunctionalBlock::createProductionPattern()";\r
193 #ifdef DEBUG_FCTNAME\r
194   cout << "call to " << qPrintable(fctName) << endl;\r
195 #endif\r
196   \r
197   lengthPP = -1;\r
198   bool ok = true; \r
199   QHash<QString,QString> prodPattern = implementation->getProductionPattern();  \r
200   \r
201   foreach(AbstractInterface* iface, getControlOutputs()) {    \r
202     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
203     QString refName = connIface->getReference()->getName();    \r
204     if (! prodPattern.contains(refName)) {\r
205       cerr << "no production pattern for reference interface " << qPrintable(refName) << endl;\r
206       return false;\r
207     }\r
208     QList<char>* pattern = expandPattern(prodPattern.value(refName),&ok);\r
209     if (!ok) return false;\r
210     productionPattern.insert(connIface,pattern);\r
211     if (lengthPP == -1) {\r
212       lengthPP = pattern->size();\r
213     }\r
214     else {\r
215       if (pattern->size() != lengthPP) return false;\r
216     }\r
217   }    \r
218   return true;\r
219 }\r
220 \r
221 bool FunctionalBlock::createProductionCounter() {\r
222   static QString fctName = "FunctionalBlock::createProductionCounter()";\r
223 #ifdef DEBUG_FCTNAME\r
224   cout << "call to " << qPrintable(fctName) << endl;\r
225 #endif\r
226   \r
227   QStringList counterParts = implementation->getProductionCounter().split(",");\r
228   foreach(QString s, counterParts) {\r
229     cout << "cont part = " << qPrintable(s) << endl;\r
230     bool ok;\r
231     double val = s.toDouble(&ok);\r
232     if (ok) {\r
233       productionCounter.append(val);\r
234     }\r
235     else if (s.at(0) == '{') {\r
236       s.remove(0,1);\r
237       s.chop(1);\r
238       QStringList gen = s.split(":");\r
239       if (gen.size() != 3) return false;\r
240       int start = 0;\r
241       int nb = 0;\r
242       int step = 0;\r
243       for(int i=0;i<3;i++) {\r
244         bool okVal;\r
245         double result = evaluateExpression(gen.at(i),&okVal);\r
246         if (!okVal) return false;\r
247         if (i==0) start = result;\r
248         else if (i==1) nb = result;\r
249         else if (i==2) step = result;\r
250       }\r
251       for(int j=0;j<nb;j++) {\r
252         productionCounter.append(start+j*step);\r
253       }\r
254     }\r
255     else {\r
256       bool okVal;\r
257       double result = evaluateExpression(s,&okVal);\r
258       \r
259       if (!okVal) return false;\r
260       productionCounter.append(result);      \r
261     }\r
262   }\r
263   foreach(int val, productionCounter) {\r
264     cout << val << ",";\r
265   }\r
266   cout << endl;\r
267   \r
268   return true;\r
269 }\r
270 \r
271 QList<char>* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) {\r
272   static QString fctName = "FunctionalBlock::expandPattern()";\r
273 #ifdef DEBUG_FCTNAME\r
274   cout << "call to " << qPrintable(fctName) << endl;\r
275 #endif\r
276   \r
277   QList<char> lst;\r
278   QString  p = patternIn;\r
279   p.append(')');\r
280   int offset = 0;\r
281   QList<char>* patternOut = new QList<char>();\r
282   expandPatternRecur(p,&offset,ok,patternOut);   \r
283   return patternOut;\r
284 }\r
285 \r
286 void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, bool *ok, QList<char>* patternOut) {  \r
287   \r
288   while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) {\r
289     \r
290     QChar c = patternIn.at(*offset);\r
291     if (c == '(') {\r
292       *offset += 1;\r
293       expandPatternRecur(patternIn,offset, ok, patternOut);\r
294       if (!ok) {\r
295         return;\r
296       }\r
297     }\r
298     else if (c == '0') {\r
299       patternOut->append(0);\r
300     }\r
301     else if (c == '1') {\r
302       patternOut->append(1);\r
303     }\r
304     else if (c == 'X') {\r
305       patternOut->append(-1);\r
306     }\r
307     else if (c == '{') {\r
308       *offset += 1;\r
309       QString expr = "";      \r
310       while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {\r
311         expr += patternIn.at(*offset);        \r
312         *offset += 1;\r
313       }\r
314       if (*offset == patternIn.size()) {\r
315         *ok = false;\r
316         return;\r
317       }\r
318       double repeat = evaluateExpression(expr,ok);\r
319       if (!ok) {\r
320         return;      \r
321       }            \r
322       // repeat just the last value in currentGroup\r
323       char last = patternOut->last();      \r
324       //cout << "repeat last char " << repeat << " times : " << (int)last << endl;\r
325       \r
326       for(int i=1;i<(int)repeat;i++) {\r
327         patternOut->append(last);\r
328       }\r
329     }    \r
330     *offset += 1;\r
331   }\r
332   \r
333   // must check if after ), there is a {\r
334   if ((*offset < patternIn.size()-1) && (patternIn.at(*offset+1) == '{')) {\r
335     *offset += 2;\r
336     QString expr = "";      \r
337     while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {\r
338       expr += patternIn.at(*offset);        \r
339       *offset += 1;\r
340     }\r
341     if (*offset == patternIn.size()) {\r
342       *ok = false;\r
343       return;\r
344     }\r
345     double repeat = evaluateExpression(expr,ok);\r
346     if (!ok) {\r
347       return;      \r
348     }\r
349     /*\r
350     cout << "repeat last group " << repeat << " times : ";\r
351     foreach (char c, currentGroup) cout <<(int)c;\r
352     cout << endl;  \r
353     */\r
354     QList<char> single = *patternOut;\r
355     for(int i=1;i<(int)repeat;i++) {\r
356       patternOut->append(single);\r
357     }    \r
358   }\r
359   //*offset += 1;\r
360   return;\r
361 }\r
362 \r
363 double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) {\r
364   static QString fctName = "FunctionalBlock::evaluateExpression()";\r
365 #ifdef DEBUG_FCTNAME\r
366   cout << "call to " << qPrintable(fctName) << endl;\r
367 #endif\r
368   \r
369   *ok = true;\r
370   QHash<QString,double> vars;\r
371   evaluator->setExpression(expression);\r
372   QList<QString> varNames = evaluator->getVariableNames();\r
373   foreach (QString name, varNames) {\r
374     QString paramName = name;\r
375     paramName.remove(0,1);\r
376     BlockParameter* param = reference->getParameterFromName(paramName);    \r
377     if (param == NULL) {\r
378       cerr << "found an unknown parameter in delta"<< endl;\r
379       *ok = false;\r
380       return 0.0;\r
381     }\r
382     bool okVal;\r
383     int val = param->getDoubleValue(&okVal);\r
384     if (!okVal) {\r
385       cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl;\r
386       *ok = false;\r
387       return 0.0;\r
388     }\r
389     vars.insert(name,(double)val);    \r
390   }\r
391   \r
392   evaluator->setVariablesValue(vars);\r
393   double result;\r
394   try {\r
395     result = evaluator->evaluate();\r
396   }\r
397   catch(int index) {\r
398     cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;\r
399     *ok = false;\r
400     return 0.0;\r
401   }\r
402   return result;\r
403 }\r
404 \r
405 void FunctionalBlock::createInputPattern() {\r
406   static QString fctName = "FunctionalBlock::createInputPattern())";\r
407 #ifdef DEBUG_FCTNAME\r
408   cout << "call to " << qPrintable(fctName) << endl;\r
409 #endif\r
410   \r
411   lengthIP = -1;\r
412   foreach(AbstractInterface* iface, getControlInputs()) {      \r
413     ConnectedInterface* connIface = AI_TO_CON(iface);\r
414     QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();\r
415     if (lengthIP == -1) {\r
416       lengthIP = out->size();\r
417     }\r
418     else {\r
419       if (out->size() < lengthIP) lengthIP = out->size();\r
420     }\r
421     if (out->size() > 0) {\r
422       QList<char>* in = new QList<char>(*out);\r
423       foreach(char c, *in) {\r
424         cout << (int)c;\r
425       }\r
426       cout << endl;\r
427 \r
428       inputPattern.insert(connIface,in);\r
429     }\r
430     else {\r
431       inputPattern.insert(connIface,NULL);\r
432     }      \r
433   }\r
434   // remove null columns at the end of IP\r
435   while(! isValidDataGroup(inputPattern,lengthIP-1)) {\r
436     removeDataGroup(inputPattern,lengthIP-1);\r
437     lengthIP -= 1;\r
438   }\r
439 }\r
440 \r
441 bool FunctionalBlock::createAdmittance(int nbExec) {\r
442   static QString fctName = "FunctionalBlock::createAdmittance()";\r
443 #ifdef DEBUG_FCTNAME\r
444   cout << "call to " << qPrintable(fctName) << endl;\r
445 #endif\r
446   bool ok = true;\r
447   // firstly, copy CP in AP\r
448   QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);\r
449   while (iterC.hasNext()) {\r
450     iterC.next();\r
451     QList<char>* pattern = new QList<char>(*(iterC.value()));\r
452     admittance.insert(iterC.key(), pattern);    \r
453   }\r
454   lengthAP = lengthCP;\r
455   int clock = 0;  \r
456   cout << "trigger 1 at c.c. 0" << endl;\r
457   for(int i=1;i<nbExec;i++) {\r
458     // searching for the clock cycle for which a new exec starts\r
459     int nbGroup = 0;\r
460     while ((clock < lengthAP) && (nbGroup < delta)) {\r
461       if (isValidDataGroup(admittance,clock)) nbGroup+=1;\r
462       clock += 1;\r
463     }\r
464     while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;\r
465     cout << "trigger " << (i+1) << " at c.c. " << clock << endl;\r
466     int sc = clock;\r
467     // combine CP with AP at sc\r
468     for(int j=0;j<lengthCP;j++) {\r
469       // first case : column of CP must be placed beyond AP's end.\r
470       if (sc == lengthAP) {\r
471         cout << i << "," << j << " append in AP at " << sc << endl;\r
472         appendToPattern(consumptionPattern,j,admittance,1);\r
473         lengthAP += 1;\r
474         sc += 1;               \r
475       }\r
476       // second case : CP and AP can be combined directly (i.e. no X | 1 to do)\r
477       else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
478         cout << i << "," << j << " combine at " << sc << endl;\r
479         combinePatterns(consumptionPattern,j,admittance,sc);\r
480         sc += 1;\r
481       }\r
482       // third case : CP has an X column\r
483       else if (isOnlyXDataGroup(consumptionPattern,j)) {\r
484         cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;\r
485         shiftRightPattern(admittance,sc);\r
486         lengthAP += 1;\r
487         if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
488           cerr << "Abnormal case when combining AP and CP" << endl;\r
489         }\r
490         combinePatterns(consumptionPattern,j,admittance,sc);        \r
491         sc += 1;\r
492       }\r
493       // fourth case : AP has an X column\r
494       else if (isOnlyXDataGroup(admittance,sc)) {\r
495         cout << i << "," << j << " jump c.c. for CP at " << sc << endl;        \r
496         sc += 1;\r
497         j -= 1;\r
498       }\r
499       else {\r
500         cout << "AP and CP are not consistent" << endl;\r
501         return false;\r
502       }\r
503     }\r
504   }\r
505   // turn all X into 0\r
506   QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);\r
507   while (iterA.hasNext()) {\r
508     iterA.next();\r
509     QList<char>* pattern = iterA.value();\r
510     for(int i=0;i<pattern->size();i++) {\r
511       if (pattern->at(i) == -1) pattern->replace(i,0);\r
512       cout << (int)(pattern->at(i));\r
513     }\r
514     cout << endl;\r
515   }\r
516   return true;\r
517 }\r
518 \r
519 bool FunctionalBlock::checkInputPatternCompatibility() {\r
520   static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
521 #ifdef DEBUG_FCTNAME\r
522   cout << "call to " << qPrintable(fctName) << endl;\r
523 #endif\r
524   \r
525   bool ok = true;\r
526   // firstly, create input pattern\r
527   createInputPattern();      \r
528   // if some patterns are not available, end now, returning false\r
529   if (lengthIP == 0) {\r
530     clearInputPattern();\r
531     return false;\r
532   }\r
533   int nbExec = getNumberOfExecution();\r
534   cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;\r
535   \r
536   ok = createAdmittance(nbExec);\r
537   \r
538   if (!ok) {\r
539     cout << "cannot create admittance" << endl;\r
540     return false;\r
541   }\r
542   \r
543   int clock = 0; // index in IP  \r
544   int i = 0; // index in AP  \r
545   while ((clock < lengthIP) && (i < lengthAP)) {\r
546      \r
547     // if AP is a valid group, search for the next valid group in IP\r
548     if (isValidDataGroup(admittance,i)) {\r
549       while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
550       if (clock == lengthIP) {\r
551         cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;\r
552         return false;\r
553       }\r
554     }    \r
555     /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or\r
556        are both null columns\r
557     */\r
558     if (! samePatterns(inputPattern,clock,admittance,i)) {\r
559       cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;\r
560       return false;\r
561     }\r
562     clock++;\r
563     i++;\r
564   }\r
565   if (clock < lengthIP) {\r
566     cerr << "Abnormal case: AP is to short" << endl;\r
567     return false;\r
568   }\r
569   return true;\r
570 }\r
571 \r
572 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
573   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
574 #ifdef DEBUG_FCTNAME\r
575   cout << "call to " << qPrintable(fctName) << endl;\r
576 #endif\r
577   \r
578   /* case 1: the block is a generator for which output pattern\r
579      must be computed for a nbExec following executions\r
580   */\r
581   \r
582   \r
583   if (nbExec > 0) {\r
584     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
585     foreach(AbstractInterface* iface, getControlOutputs()) {\r
586       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
587       // create output pattern\r
588       QList<char>* pp = productionPattern.value(connIface);\r
589       QList<char>* pattern = new QList<char>(*pp);\r
590       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
591       // assign pattern to interface\r
592       connIface->setOutputPattern(pattern);\r
593       // store it in QMap\r
594       outputPattern.insert(connIface,pattern);      \r
595     }\r
596   }\r
597   else {\r
598     cout << "computing output pattern of " << qPrintable(name) << endl;\r
599     \r
600     // in case of inputPattern not created, do it\r
601     if (lengthIP <= 0) {\r
602       // collect the input patterns for each input    \r
603       createInputPattern();    \r
604       // if some patterns are not available, end now, returning false\r
605       if (lengthIP == 0) {\r
606         clearInputPattern();\r
607         return false;\r
608       }\r
609       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
610     }\r
611     \r
612     // initialize the output pattern    \r
613     lengthOP = 0;\r
614     foreach(AbstractInterface* iface, getControlOutputs()) {\r
615       FunctionalInterface* connIface = AI_TO_FUN(iface);      \r
616       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
617       QList<char>* pattern = new QList<char>();\r
618       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
619       connIface->setOutputPattern(pattern);\r
620       outputPattern.insert(connIface,pattern);\r
621     }\r
622     cout << "output pattern array initialized" << endl;\r
623     \r
624     int clock = 0;\r
625     nbExec = 0;\r
626     // search for the beginning of the first execution.\r
627     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
628     cout << "found 1st exec clock: " << clock << endl;\r
629     \r
630     while (clock < lengthIP) {\r
631       // initialize counters for current execution.\r
632       int p = 0; // index in production pattern\r
633       int o = 0; // clock+o will give the clock cycle of each output group\r
634       int cip = 0; // clock+cip give the clock cycle of an input group\r
635       int ccp = 0; // ccp give a column in the consumptio pattern\r
636       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
637       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
638       bool cannotCompleteExec = false;\r
639       for(int m=0;m<productionCounter.size();m++) {\r
640         // search for the first production in PP\r
641         while (!isValidDataGroup(productionPattern,p)) {\r
642           p += 1;\r
643           o += 1;\r
644         }\r
645         int gap = 0; // count the number of extra null columns\r
646         // search for PC(m) valid input group in IP\r
647         while (nip < productionCounter.at(m)) {\r
648           if (clock+cip < lengthIP) {\r
649             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
650             cip += 1;\r
651             gap += 1;\r
652           }\r
653           else {\r
654             cannotCompleteExec = true;\r
655             break;\r
656           }        \r
657         }        \r
658         \r
659         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
660         \r
661         // search for PC(m) valid input group in IP\r
662         while (ncp < productionCounter.at(m)) {\r
663           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
664           ccp += 1;\r
665           gap -= 1;\r
666         }\r
667         o += gap; // to take into acocunt of extra null columns\r
668         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
669         p += 1;\r
670         o += 1;\r
671       }\r
672       \r
673       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
674       \r
675       // current exec. taken into accunt\r
676       nbExec += 1;\r
677       \r
678       // search for the next exec.\r
679       clock += 1;      \r
680       nip = 0;\r
681       while ((clock < lengthIP) && (nip < delta)) {\r
682         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
683         if (nip < delta) clock += 1;\r
684       }\r
685       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
686     }\r
687     // find the last valid output data group\r
688     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
689       removeDataGroup(outputPattern,lengthOP-1);\r
690       lengthOP -= 1;\r
691     }\r
692 \r
693     // clear input pattern\r
694     clearInputPattern();\r
695   }\r
696   return true;\r
697 }\r
698 \r
699 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
700   \r
701   if (patternSrc.size() != patternDest.size()) return false;\r
702   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
703   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
704   while (iterSrc.hasNext()) {\r
705     iterSrc.next();\r
706     iterDest.next();    \r
707     QList<char>* srcPat = iterSrc.value();\r
708     QList<char>* destPat = iterDest.value();\r
709     if (srcCol >= srcPat->size()) return false;\r
710     if (destCol >= destPat->size()) return false;\r
711     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;    \r
712   }\r
713   return true;\r
714 }\r
715 \r
716 bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
717   if (patternSrc.size() != patternDest.size()) return false;\r
718   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
719   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
720   while (iterSrc.hasNext()) {\r
721     iterSrc.next();\r
722     iterDest.next();    \r
723     QList<char>* srcPat = iterSrc.value();\r
724     QList<char>* destPat = iterDest.value();\r
725     if (srcCol >= srcPat->size()) return false;\r
726     if (destCol >= destPat->size()) return false;\r
727     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;\r
728     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;\r
729   }\r
730   return true;\r
731 }\r
732 \r
733 void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
734   if (patternSrc.size() != patternDest.size()) return;\r
735   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
736   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
737   while (iterSrc.hasNext()) {\r
738     iterSrc.next();\r
739     iterDest.next();    \r
740     QList<char>* srcPat = iterSrc.value();\r
741     QList<char>* destPat = iterDest.value();\r
742     if (srcCol >= srcPat->size()) return;\r
743     if (destCol >= destPat->size()) return;\r
744     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;\r
745     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;    \r
746     destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));\r
747   }  \r
748 }\r
749 \r
750 void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {\r
751   if (patternSrc.size() != patternDest.size()) return;\r
752   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
753   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
754   while (iterSrc.hasNext()) {\r
755     iterSrc.next();\r
756     iterDest.next();    \r
757     QList<char>* srcPat = iterSrc.value();\r
758     QList<char>* destPat = iterDest.value();    \r
759     int i=0;\r
760     while ((srcCol+i < srcPat->size()) && (i<nbCols)) {\r
761       destPat->append(srcPat->at(srcCol+i));\r
762       i++;\r
763     }\r
764   }  \r
765 }\r
766 \r
767 void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
768   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
769   while (iterSrc.hasNext()) {\r
770     iterSrc.next();    \r
771     QList<char>* srcPat = iterSrc.value();\r
772     if (offset < srcPat->size()) {\r
773       srcPat->removeAt(offset);\r
774     }\r
775   }\r
776 }\r
777 \r
778 void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
779   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
780   while (iterSrc.hasNext()) {\r
781     iterSrc.next();    \r
782     QList<char>* srcPat = iterSrc.value();\r
783     if (offset < srcPat->size()) {\r
784       srcPat->insert(offset,0);\r
785     }\r
786   }\r
787 }\r
788 \r
789 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
790   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
791   while (iterSrc.hasNext()) {\r
792     iterSrc.next();    \r
793     QList<char>* srcPat = iterSrc.value();\r
794     if (offset >= srcPat->size()) return false;\r
795     if (srcPat->at(offset) == 1) return true;\r
796   }\r
797   return false;\r
798 }\r
799 \r
800 bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
801   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
802   while (iterSrc.hasNext()) {\r
803     iterSrc.next();    \r
804     QList<char>* srcPat = iterSrc.value();\r
805     if (offset >= srcPat->size()) return false;\r
806     if (srcPat->at(offset) != -1) return false;\r
807   }\r
808   return true;  \r
809 }\r
810 \r
811 void FunctionalBlock::clearConsumptionPattern() {\r
812   QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);  \r
813   while (iterP.hasNext()) {\r
814     iterP.next();\r
815     QList<char>* pattern = iterP.value();\r
816     if (pattern != NULL) delete pattern;\r
817   }\r
818   consumptionPattern.clear();\r
819   lengthCP = -1;      \r
820 }  \r
821 \r
822 void FunctionalBlock::clearProductionPattern() {\r
823   QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);  \r
824   while (iterP.hasNext()) {\r
825     iterP.next();\r
826     QList<char>* pattern = iterP.value();\r
827     if (pattern != NULL) delete pattern;\r
828   }\r
829   productionPattern.clear();\r
830   lengthPP = -1;\r
831 }  \r
832 \r
833 void FunctionalBlock::clearInputPattern() {\r
834   \r
835   QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
836   while (iterI.hasNext()) {\r
837     iterI.next();\r
838     QList<char>* pattern = iterI.value();\r
839     if (pattern != NULL) delete pattern;\r
840   }\r
841   inputPattern.clear();\r
842   lengthIP = -1;\r
843 }\r
844 \r
845 int FunctionalBlock::getNumberOfExecution() {\r
846   /* NB: this method returns the number of executions that have been started\r
847      but not necessary completed.\r
848   */\r
849   if (delta <= 0) return 0;\r
850   int nbExec = 0;\r
851   int offset = 0;\r
852   // search for the first exec.\r
853   while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;\r
854   if (offset == lengthIP) return 0;\r
855   nbExec = 1;\r
856   int nbGroup = 0;\r
857   for(int i = offset;i<lengthIP;i++) {\r
858     if (isValidDataGroup(inputPattern,i)) nbGroup++;\r
859     if (nbGroup == delta+1) {\r
860       nbExec += 1;\r
861       nbGroup = 1;\r
862     }\r
863   }      \r
864   return nbExec;  \r
865 }\r