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

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