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

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