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

Private GIT Repository
patter compat continued
[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 }\r
435 \r
436 bool FunctionalBlock::createAdmittance(int nbExec) {\r
437   static QString fctName = "FunctionalBlock::createAdmittance()";\r
438 #ifdef DEBUG_FCTNAME\r
439   cout << "call to " << qPrintable(fctName) << endl;\r
440 #endif\r
441   bool ok = true;\r
442   // firstly, copy CP in AP\r
443   QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);\r
444   while (iterC.hasNext()) {\r
445     iterC.next();\r
446     QList<char>* pattern = new QList<char>(*(iterC.value()));\r
447     admittance.insert(iterC.key(), pattern);    \r
448   }\r
449   lengthAP = lengthCP;\r
450   int clock = 0;  \r
451   cout << "trigger 1 at c.c. 0" << endl;\r
452   for(int i=1;i<nbExec;i++) {\r
453     // searching for the clock cycle for which a new exec starts\r
454     int nbGroup = 0;\r
455     while ((clock < lengthAP) && (nbGroup < delta)) {\r
456       if (isValidDataGroup(admittance,clock)) nbGroup+=1;\r
457       clock += 1;\r
458     }\r
459     while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;\r
460     cout << "trigger " << (i+1) << " at c.c. " << clock << endl;\r
461     int sc = clock;\r
462     // combine CP with AP at sc\r
463     for(int j=0;j<lengthCP;j++) {\r
464       // first case : column of CP must be placed beyond AP's end.\r
465       if (sc == lengthAP) {\r
466         cout << i << "," << j << " append in AP at " << sc << endl;\r
467         appendToPattern(consumptionPattern,j,admittance,1);\r
468         lengthAP += 1;\r
469         sc += 1;               \r
470       }\r
471       // second case : CP and AP can be combined directly (i.e. no X | 1 to do)\r
472       else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
473         cout << i << "," << j << " combine at " << sc << endl;\r
474         combinePatterns(consumptionPattern,j,admittance,sc);\r
475         sc += 1;\r
476       }\r
477       // third case : CP has an X column\r
478       else if (isOnlyXDataGroup(consumptionPattern,j)) {\r
479         cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;\r
480         shiftRightPattern(admittance,sc);\r
481         lengthAP += 1;\r
482         if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
483           cerr << "Abnormal case when combining AP and CP" << endl;\r
484         }\r
485         combinePatterns(consumptionPattern,j,admittance,sc);        \r
486         sc += 1;\r
487       }\r
488       // fourth case : AP has an X column\r
489       else if (isOnlyXDataGroup(admittance,sc)) {\r
490         cout << i << "," << j << " jump c.c. for CP at " << sc << endl;        \r
491         sc += 1;\r
492         j -= 1;\r
493       }\r
494       else {\r
495         cout << "AP and CP are not consistent" << endl;\r
496         return false;\r
497       }\r
498     }\r
499   }\r
500   // turn all X into 0\r
501   QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);\r
502   while (iterA.hasNext()) {\r
503     iterA.next();\r
504     QList<char>* pattern = iterA.value();\r
505     for(int i=0;i<pattern->size();i++) {\r
506       if (pattern->at(i) == -1) pattern->replace(i,0);\r
507     }\r
508   }\r
509   return true;\r
510 }\r
511 \r
512 bool FunctionalBlock::checkInputPatternCompatibility() {\r
513   static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
514 #ifdef DEBUG_FCTNAME\r
515   cout << "call to " << qPrintable(fctName) << endl;\r
516 #endif\r
517   \r
518   bool ok = true;\r
519   // firstly, create input pattern\r
520   createInputPattern();      \r
521   // if some patterns are not available, end now, returning false\r
522   if (lengthIP == 0) {\r
523     clearInputPattern();\r
524     return false;\r
525   }\r
526   int nbExec = getNumberOfExecution();\r
527   ok = createAdmittance(nbExec);\r
528   if (!ok) return false;\r
529   \r
530   int clock = 0; // index in IP  \r
531   int i = 0; // index in AP\r
532   while (clock < lengthIP) {\r
533     if (samePatterns(inputPattern,clock,admittance,i)) {\r
534       clock++;\r
535       i++;\r
536     }\r
537     else {\r
538       if (isValidDataGroup(admittance,i)) {\r
539         \r
540       }\r
541       else {\r
542         // IP and AP are not equal and AP is a valid group -> not compatible\r
543         return false;\r
544       }\r
545       \r
546     }    \r
547   }\r
548   return true;\r
549 }\r
550 \r
551 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
552   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
553 #ifdef DEBUG_FCTNAME\r
554   cout << "call to " << qPrintable(fctName) << endl;\r
555 #endif\r
556   \r
557   /* case 1: the block is a generator for which output pattern\r
558      must be computed for a nbExec following executions\r
559   */\r
560   \r
561   \r
562   if (nbExec > 0) {\r
563     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
564     foreach(AbstractInterface* iface, getControlOutputs()) {\r
565       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
566       // create output pattern\r
567       QList<char>* pp = productionPattern.value(connIface);\r
568       QList<char>* pattern = new QList<char>(*pp);\r
569       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
570       // assign pattern to interface\r
571       connIface->setOutputPattern(pattern);\r
572       // store it in QMap\r
573       outputPattern.insert(connIface,pattern);      \r
574     }\r
575   }\r
576   else {\r
577     cout << "computing output pattern of " << qPrintable(name) << endl;\r
578     \r
579     // in case of inputPattern not created, do it\r
580     if (lengthIP <= 0) {\r
581       // collect the input patterns for each input    \r
582       createInputPattern();    \r
583       // if some patterns are not available, end now, returning false\r
584       if (lengthIP == 0) {\r
585         clearInputPattern();\r
586         return false;\r
587       }\r
588       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
589     }\r
590     \r
591     // initialize the output pattern    \r
592     lengthOP = 0;\r
593     foreach(AbstractInterface* iface, getControlOutputs()) {\r
594       FunctionalInterface* connIface = AI_TO_FUN(iface);      \r
595       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
596       QList<char>* pattern = new QList<char>();\r
597       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
598       connIface->setOutputPattern(pattern);\r
599       outputPattern.insert(connIface,pattern);\r
600     }\r
601     cout << "output pattern array initialized" << endl;\r
602     \r
603     int clock = 0;\r
604     nbExec = 0;\r
605     // search for the beginning of the first execution.\r
606     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
607     cout << "found 1st exec clock: " << clock << endl;\r
608     \r
609     while (clock < lengthIP) {\r
610       // initialize counters for current execution.\r
611       int p = 0; // index in production pattern\r
612       int o = 0; // clock+o will give the clock cycle of each output group\r
613       int cip = 0; // clock+cip give the clock cycle of an input group\r
614       int ccp = 0; // ccp give a column in the consumptio pattern\r
615       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
616       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
617       bool cannotCompleteExec = false;\r
618       for(int m=0;m<productionCounter.size();m++) {\r
619         // search for the first production in PP\r
620         while (!isValidDataGroup(productionPattern,p)) {\r
621           p += 1;\r
622           o += 1;\r
623         }\r
624         int gap = 0; // count the number of extra null columns\r
625         // search for PC(m) valid input group in IP\r
626         while (nip < productionCounter.at(m)) {\r
627           if (clock+cip < lengthIP) {\r
628             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
629             cip += 1;\r
630             gap += 1;\r
631           }\r
632           else {\r
633             cannotCompleteExec = true;\r
634             break;\r
635           }        \r
636         }        \r
637         \r
638         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
639         \r
640         // search for PC(m) valid input group in IP\r
641         while (ncp < productionCounter.at(m)) {\r
642           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
643           ccp += 1;\r
644           gap -= 1;\r
645         }\r
646         o += gap; // to take into acocunt of extra null columns\r
647         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
648         p += 1;\r
649         o += 1;\r
650       }\r
651       \r
652       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
653       \r
654       // current exec. taken into accunt\r
655       nbExec += 1;\r
656       \r
657       // search for the next exec.\r
658       clock += 1;      \r
659       nip = 0;\r
660       while ((clock < lengthIP) && (nip < delta)) {\r
661         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
662         if (nip < delta) clock += 1;\r
663       }\r
664       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
665     }\r
666     // find the last valid output data group\r
667     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
668       removeDataGroup(outputPattern,lengthOP-1);\r
669       lengthOP -= 1;\r
670     }\r
671 \r
672     // clear input pattern\r
673     clearInputPattern();\r
674   }\r
675   return true;\r
676 }\r
677 \r
678 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
679   \r
680   if (patternSrc.size() != patternDest.size()) return false;\r
681   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
682   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
683   while (iterSrc.hasNext()) {\r
684     iterSrc.next();\r
685     iterDest.next();    \r
686     QList<char>* srcPat = iterSrc.value();\r
687     QList<char>* destPat = iterDest.value();\r
688     if (srcCol >= srcPat->size()) return false;\r
689     if (destCol >= destPat->size()) return false;\r
690     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;    \r
691   }\r
692   return true;\r
693 }\r
694 \r
695 bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
696   if (patternSrc.size() != patternDest.size()) return false;\r
697   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
698   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
699   while (iterSrc.hasNext()) {\r
700     iterSrc.next();\r
701     iterDest.next();    \r
702     QList<char>* srcPat = iterSrc.value();\r
703     QList<char>* destPat = iterDest.value();\r
704     if (srcCol >= srcPat->size()) return false;\r
705     if (destCol >= destPat->size()) return false;\r
706     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;\r
707     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;\r
708   }\r
709   return true;\r
710 }\r
711 \r
712 void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
713   if (patternSrc.size() != patternDest.size()) return;\r
714   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
715   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
716   while (iterSrc.hasNext()) {\r
717     iterSrc.next();\r
718     iterDest.next();    \r
719     QList<char>* srcPat = iterSrc.value();\r
720     QList<char>* destPat = iterDest.value();\r
721     if (srcCol >= srcPat->size()) return;\r
722     if (destCol >= destPat->size()) return;\r
723     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;\r
724     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;    \r
725     destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));\r
726   }  \r
727 }\r
728 \r
729 void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {\r
730   if (patternSrc.size() != patternDest.size()) return;\r
731   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
732   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
733   while (iterSrc.hasNext()) {\r
734     iterSrc.next();\r
735     iterDest.next();    \r
736     QList<char>* srcPat = iterSrc.value();\r
737     QList<char>* destPat = iterDest.value();    \r
738     int i=0;\r
739     while ((srcCol+i < srcPat->size()) && (i<nbCols)) {\r
740       destPat->append(srcPat->at(srcCol+i));\r
741       i++;\r
742     }\r
743   }  \r
744 }\r
745 \r
746 void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
747   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
748   while (iterSrc.hasNext()) {\r
749     iterSrc.next();    \r
750     QList<char>* srcPat = iterSrc.value();\r
751     if (offset < srcPat->size()) {\r
752       srcPat->removeAt(offset);\r
753     }\r
754   }\r
755 }\r
756 \r
757 void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
758   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
759   while (iterSrc.hasNext()) {\r
760     iterSrc.next();    \r
761     QList<char>* srcPat = iterSrc.value();\r
762     if (offset < srcPat->size()) {\r
763       srcPat->insert(offset,0);\r
764     }\r
765   }\r
766 }\r
767 \r
768 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
769   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
770   while (iterSrc.hasNext()) {\r
771     iterSrc.next();    \r
772     QList<char>* srcPat = iterSrc.value();\r
773     if (offset >= srcPat->size()) return false;\r
774     if (srcPat->at(offset) == 1) return true;\r
775   }\r
776   return false;\r
777 }\r
778 \r
779 bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
780   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
781   while (iterSrc.hasNext()) {\r
782     iterSrc.next();    \r
783     QList<char>* srcPat = iterSrc.value();\r
784     if (offset >= srcPat->size()) return false;\r
785     if (srcPat->at(offset) != -1) return false;\r
786   }\r
787   return true;  \r
788 }\r
789 \r
790 void FunctionalBlock::clearConsumptionPattern() {\r
791   QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);  \r
792   while (iterP.hasNext()) {\r
793     iterP.next();\r
794     QList<char>* pattern = iterP.value();\r
795     if (pattern != NULL) delete pattern;\r
796   }\r
797   consumptionPattern.clear();\r
798   lengthCP = -1;      \r
799 }  \r
800 \r
801 void FunctionalBlock::clearProductionPattern() {\r
802   QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);  \r
803   while (iterP.hasNext()) {\r
804     iterP.next();\r
805     QList<char>* pattern = iterP.value();\r
806     if (pattern != NULL) delete pattern;\r
807   }\r
808   productionPattern.clear();\r
809   lengthPP = -1;\r
810 }  \r
811 \r
812 void FunctionalBlock::clearInputPattern() {\r
813   \r
814   QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
815   while (iterI.hasNext()) {\r
816     iterI.next();\r
817     QList<char>* pattern = iterI.value();\r
818     if (pattern != NULL) delete pattern;\r
819   }\r
820   inputPattern.clear();\r
821   lengthIP = -1;\r
822 }\r
823 \r
824 int FunctionalBlock::getNumberOfExecution() {\r
825   /* NB: this method returns the number of executions that have been started\r
826      but not necessary completed.\r
827   */\r
828   if (delta <= 0) return 0;\r
829   int nbExec = 0;\r
830   int offset = 0;\r
831   // search for the first exec.\r
832   while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;\r
833   if (offset == lengthIP) return 0;\r
834   nbExec = 1;\r
835   int nbGroup = 0;\r
836   for(int i = offset;i<lengthIP;i++) {\r
837     if (isValidDataGroup(inputPattern,offset)) nbGroup++;\r
838     if (nbGroup == delta+1) {\r
839       nbExec += 1;\r
840       nbGroup = 1;\r
841     }\r
842   }      \r
843   return nbExec;  \r
844 }\r