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

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