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

Private GIT Repository
0db21c42398801f2097a9cc7c506f6ffb1d51da4
[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   consumptionPattern = NULL;\r
18   lengthCP = 0;\r
19   nbConsumingPorts = 0;\r
20   productionPattern = NULL;\r
21   lengthPP = 0;\r
22   nbProducingPorts = 0;\r
23   if (reference->getImplementations().isEmpty()) {\r
24     implementation = NULL;\r
25     cout << "block has no implementation" << endl;\r
26   }\r
27   else {\r
28     implementation = reference->getImplementations().at(0);\r
29   }\r
30 }\r
31 \r
32 \r
33 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {\r
34   /*\r
35   checkedBlocks->append(this);\r
36 \r
37   foreach(BlockParameter* param, params){\r
38     if(param->isUserParameter() && !param->isValueSet()){\r
39       if(!blocksToConfigure->contains(param->getOwner())){\r
40         blocksToConfigure->append(param->getOwner());\r
41       }\r
42     }\r
43   }\r
44   foreach(AbstractInterface *inter, outputs){\r
45     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
46       if(!checkedBlocks->contains(connectedInter->getOwner())){\r
47         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
48       }\r
49     }\r
50   }\r
51   */\r
52 }\r
53 \r
54 bool FunctionalBlock::isFunctionalBlock() {\r
55   return true;\r
56 }\r
57 \r
58 bool FunctionalBlock::isSourceBlock() {\r
59   if (parent == NULL) return true;\r
60   return false;\r
61 }\r
62 \r
63 void FunctionalBlock::populate() {\r
64   int i;\r
65   BlockParameter* p;\r
66   AbstractInterface* inter;\r
67 \r
68   // create parameters from reference block\r
69   QList<BlockParameter*> lstParam = reference->getParameters();\r
70   for(i=0;i<lstParam.size();i++) {\r
71     p = lstParam.at(i)->clone();\r
72     addParameter(p);\r
73   }\r
74 \r
75   // create interfaces from reference block\r
76   QList<AbstractInterface *> lstRef = reference->getInterfaces();\r
77   // store relation between functional and reference\r
78   QHash<AbstractInterface *, AbstractInterface *> hashIface;\r
79   for(i=0;i<lstRef.size();i++) {\r
80     try {\r
81       inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));\r
82     }\r
83     catch(Exception e) {\r
84       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
85       exit(1);\r
86     }\r
87     hashIface.insert(lstRef.at(i),inter);\r
88 \r
89     addInterface(inter);\r
90   }\r
91     \r
92   AbstractInterface* funCtlIface = NULL;\r
93   AbstractInterface* funDataIface = NULL;\r
94   \r
95   for(i=0;i<lstRef.size();i++) {    \r
96     AbstractInterface* refIface = lstRef.at(i);    \r
97     if (refIface->getPurpose() == AbstractInterface::Control) {\r
98       funCtlIface = hashIface.value(refIface);\r
99       funDataIface = hashIface.value(refIface->getAssociatedIface());\r
100       if (! funCtlIface->setAssociatedIface(funDataIface)) {\r
101         cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;\r
102         exit(1);\r
103       }       \r
104     }\r
105   }\r
106 }\r
107 \r
108 \r
109 QString FunctionalBlock::getReferenceXmlFile() {\r
110     return ((ReferenceBlock *)reference)->getXmlFile();\r
111 }\r
112 \r
113 QString FunctionalBlock::getReferenceHashMd5() {\r
114     return ((ReferenceBlock *)reference)->getHashMd5();\r
115 }\r
116 \r
117 bool FunctionalBlock::createPatterns() {\r
118   static QString fctName = "FunctionalBlock::createPatterns()";\r
119 #ifdef DEBUG_FCTNAME\r
120   cout << "call to " << qPrintable(fctName) << endl;\r
121 #endif\r
122   \r
123   cout << "create patterns for block " << qPrintable(name) << endl;\r
124   evaluator = new ArithmeticEvaluator();\r
125   bool ok = true;\r
126   ok = ok & createDelta();\r
127   if (! isGeneratorBlock()) {\r
128     if (ok) ok = ok & createConsumptionPattern();\r
129     if (ok) ok = ok & createProductionCounter();\r
130   }\r
131   if (ok) ok = ok & createProductionPattern();\r
132   delete evaluator;\r
133   return ok;\r
134 }\r
135 \r
136 bool FunctionalBlock::createDelta() {\r
137   static QString fctName = "FunctionalBlock::createDelta()";\r
138 #ifdef DEBUG_FCTNAME\r
139   cout << "call to " << qPrintable(fctName) << endl;\r
140 #endif \r
141   \r
142   QString deltaStr = implementation->getDelta();\r
143   cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;\r
144   \r
145   // look for parameter names\r
146   bool ok = true;\r
147   double result = evaluateExpression(deltaStr, &ok);\r
148   if (!ok) return false;\r
149   \r
150   delta = result;\r
151   cout << "delta = " << delta << endl;\r
152    \r
153   return true;\r
154 }\r
155 \r
156 bool FunctionalBlock::createConsumptionPattern() {\r
157   static QString fctName = "FunctionalBlock::createConsumptionPattern()";\r
158 #ifdef DEBUG_FCTNAME\r
159   cout << "call to " << qPrintable(fctName) << endl;\r
160 #endif\r
161   \r
162   bool ok = true; \r
163   QHash<QString,QString> consPattern = implementation->getConsumptionPattern();  \r
164   \r
165   foreach(AbstractInterface* iface, getControlInputs()) {       \r
166     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
167     QString refName = connIface->getReference()->getName();    \r
168     if (! consPattern.contains(refName)) {\r
169       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;\r
170       return false;\r
171     }\r
172     QList<char> pattern = expandPattern(consPattern.value(refName),&ok);    \r
173     \r
174     if (!ok) return false;\r
175     connIface->setConsumptionPattern(pattern);\r
176     cout << qPrintable(refName) << " consumption pattern = ";\r
177     foreach(char c, pattern) {\r
178       cout << (int)c << " ";\r
179     }\r
180     cout << endl;\r
181     \r
182   }        \r
183   return true;\r
184 }\r
185 \r
186 bool FunctionalBlock::createProductionPattern() {  \r
187   static QString fctName = "FunctionalBlock::createProductionPattern()";\r
188 #ifdef DEBUG_FCTNAME\r
189   cout << "call to " << qPrintable(fctName) << endl;\r
190 #endif\r
191   \r
192   bool ok = true; \r
193   QHash<QString,QString> prodPattern = implementation->getProductionPattern();  \r
194   \r
195   foreach(AbstractInterface* iface, getControlOutputs()) {    \r
196     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
197     QString refName = connIface->getReference()->getName();    \r
198     if (! prodPattern.contains(refName)) {\r
199       cerr << "no production pattern for reference interface " << qPrintable(refName) << endl;\r
200       return false;\r
201     }\r
202     QList<char> pattern = expandPattern(prodPattern.value(refName),&ok);\r
203     if (!ok) return false;\r
204     connIface->setProductionPattern(pattern);\r
205     cout << qPrintable(refName) << " production pattern = ";\r
206     foreach(char c, pattern) {\r
207       cout << (int)c << " ";\r
208     }\r
209     cout << endl;\r
210     \r
211   }    \r
212   return true;\r
213 }\r
214 \r
215 bool FunctionalBlock::createProductionCounter() {\r
216   static QString fctName = "FunctionalBlock::createProductionCounter()";\r
217 #ifdef DEBUG_FCTNAME\r
218   cout << "call to " << qPrintable(fctName) << endl;\r
219 #endif\r
220   \r
221   QStringList counterParts = implementation->getProductionCounter().split(",");\r
222   foreach(QString s, counterParts) {\r
223     cout << "cont part = " << qPrintable(s) << endl;\r
224     bool ok;\r
225     double val = s.toDouble(&ok);\r
226     if (ok) {\r
227       productionCounter.append(val);\r
228     }\r
229     else if (s.at(0) == '{') {\r
230       s.remove(0,1);\r
231       s.chop(1);\r
232       QStringList gen = s.split(":");\r
233       if (gen.size() != 3) return false;\r
234       int start = 0;\r
235       int nb = 0;\r
236       int step = 0;\r
237       for(int i=0;i<3;i++) {\r
238         bool okVal;\r
239         double result = evaluateExpression(gen.at(i),&okVal);\r
240         if (!okVal) return false;\r
241         if (i==0) start = result;\r
242         else if (i==1) nb = result;\r
243         else if (i==2) step = result;\r
244       }\r
245       for(int j=0;j<nb;j++) {\r
246         productionCounter.append(start+j*step);\r
247       }\r
248     }\r
249     else {\r
250       bool okVal;\r
251       double result = evaluateExpression(s,&okVal);\r
252       \r
253       if (!okVal) return false;\r
254       productionCounter.append(result);      \r
255     }\r
256   }\r
257   foreach(int val, productionCounter) {\r
258     cout << val << ",";\r
259   }\r
260   cout << endl;\r
261   \r
262   return true;\r
263 }\r
264 \r
265 QList<char> FunctionalBlock::expandPattern(const QString& pattern, bool* ok) {\r
266   static QString fctName = "FunctionalBlock::expandPattern()";\r
267 #ifdef DEBUG_FCTNAME\r
268   cout << "call to " << qPrintable(fctName) << endl;\r
269 #endif\r
270   \r
271   QList<char> lst;\r
272   QString  p = pattern;\r
273   p.append(')');\r
274   int offset = 0;\r
275   lst = expandPatternRecur(p,&offset,ok);   \r
276   return lst;\r
277 }\r
278 \r
279 QList<char> FunctionalBlock::expandPatternRecur(const QString& pattern, int *offset, bool *ok) {\r
280   \r
281   QList<char> currentGroup; \r
282   \r
283   while ((*offset < pattern.size()) && (pattern.at(*offset) != ')')) {\r
284     \r
285     QChar c = pattern.at(*offset);\r
286     if (c == '(') {\r
287       *offset += 1;\r
288       currentGroup += expandPatternRecur(pattern,offset, ok);\r
289       if (!ok) {\r
290         return currentGroup;\r
291       }\r
292     }\r
293     else if (c == '0') {\r
294       currentGroup.append(0);\r
295     }\r
296     else if (c == '1') {\r
297       currentGroup.append(1);\r
298     }\r
299     else if (c == 'X') {\r
300       currentGroup.append(-1);\r
301     }\r
302     else if (c == '{') {\r
303       *offset += 1;\r
304       QString expr = "";      \r
305       while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {\r
306         expr += pattern.at(*offset);        \r
307         *offset += 1;\r
308       }\r
309       if (*offset == pattern.size()) {\r
310         *ok = false;\r
311         return currentGroup;\r
312       }\r
313       double repeat = evaluateExpression(expr,ok);\r
314       if (!ok) {\r
315         return currentGroup;      \r
316       }            \r
317       // repeat just the last value in currentGroup\r
318       char last = currentGroup.last();      \r
319       //cout << "repeat last char " << repeat << " times : " << (int)last << endl;\r
320       \r
321       for(int i=1;i<(int)repeat;i++) {\r
322         currentGroup += last;\r
323       }\r
324     }    \r
325     *offset += 1;\r
326   }\r
327   \r
328   // must check if after ), there is a {\r
329   if ((*offset < pattern.size()-1) && (pattern.at(*offset+1) == '{')) {\r
330     *offset += 2;\r
331     QString expr = "";      \r
332     while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {\r
333       expr += pattern.at(*offset);        \r
334       *offset += 1;\r
335     }\r
336     if (*offset == pattern.size()) {\r
337       *ok = false;\r
338       return currentGroup;\r
339     }\r
340     double repeat = evaluateExpression(expr,ok);\r
341     if (!ok) {\r
342       return currentGroup;      \r
343     }\r
344     /*\r
345     cout << "repeat last group " << repeat << " times : ";\r
346     foreach (char c, currentGroup) cout <<(int)c;\r
347     cout << endl;  \r
348     */\r
349     QList<char> single = currentGroup;\r
350     for(int i=1;i<(int)repeat;i++) {\r
351       currentGroup += single;\r
352     }    \r
353   }\r
354   //*offset += 1;\r
355   return currentGroup;\r
356 }\r
357 \r
358 double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) {\r
359   static QString fctName = "FunctionalBlock::evaluateExpression()";\r
360 #ifdef DEBUG_FCTNAME\r
361   cout << "call to " << qPrintable(fctName) << endl;\r
362 #endif\r
363   \r
364   *ok = true;\r
365   QHash<QString,double> vars;\r
366   evaluator->setExpression(expression);\r
367   QList<QString> varNames = evaluator->getVariableNames();\r
368   foreach (QString name, varNames) {\r
369     QString paramName = name;\r
370     paramName.remove(0,1);\r
371     BlockParameter* param = reference->getParameterFromName(paramName);    \r
372     if (param == NULL) {\r
373       cerr << "found an unknown parameter in delta"<< endl;\r
374       *ok = false;\r
375       return 0.0;\r
376     }\r
377     bool okVal;\r
378     int val = param->getDoubleValue(&okVal);\r
379     if (!okVal) {\r
380       cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl;\r
381       *ok = false;\r
382       return 0.0;\r
383     }\r
384     vars.insert(name,(double)val);    \r
385   }  \r
386   evaluator->setVariablesValue(vars);\r
387   double result;\r
388   try {\r
389     result = evaluator->evaluate();\r
390   }\r
391   catch(int index) {\r
392     cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;\r
393     *ok = false;\r
394     return 0.0;\r
395   }\r
396   return result;\r
397 }\r
398 \r
399 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
400   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
401 #ifdef DEBUG_FCTNAME\r
402   cout << "call to " << qPrintable(fctName) << endl;\r
403 #endif\r
404   \r
405   /* case 1: the block is a generator for which output pattern\r
406      must be computed for a nbExec following executions\r
407   */\r
408   \r
409   \r
410   if (nbExec > 0) {\r
411     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
412     foreach(AbstractInterface* iface, getControlOutputs()) {\r
413       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
414       QList<char> pattern;\r
415       for(int i=0;i<nbExec;i++) pattern += connIface->getProductionPattern();\r
416       connIface->setOutputPattern(pattern);\r
417     }    \r
418   }\r
419   else {\r
420     cout << "computing output pattern of " << qPrintable(name) << endl;\r
421     \r
422     // initialize consumption and production patterns    \r
423     initConsumptionPattern();\r
424     initProductionPattern();\r
425     \r
426     // collect the input patterns for each input    \r
427     char** inputPattern = NULL;\r
428     int idIface = 0;\r
429     inputPattern = new char*[nbConsumingPorts];\r
430     int minLen = -1;\r
431     foreach(AbstractInterface* iface, getControlInputs()) {      \r
432       ConnectedInterface* connIface = AI_TO_CON(iface);\r
433       QList<char> in = connIface->getConnectedFrom()->getOutputPattern();\r
434       if (minLen == -1) {\r
435         minLen = in.size();\r
436       }\r
437       else {\r
438         if (in.size() < minLen) minLen = in.size();\r
439       }\r
440       if (in.size() > 0) {\r
441         inputPattern[idIface] = new char[in.size()];\r
442         int i = 0;\r
443         foreach(char c, in) inputPattern[idIface][i++] = c;\r
444       }\r
445       else {\r
446         inputPattern[idIface] = NULL;\r
447       }\r
448       idIface += 1;      \r
449     }\r
450     // if some patterns are not available, ens now, returning false\r
451     if (minLen == 0) {\r
452       for(int i=0;i<nbConsumingPorts; i++) {\r
453         if (inputPattern[i] != NULL) delete [] inputPattern[i];\r
454       }\r
455       delete [] inputPattern;\r
456       return false;\r
457     }\r
458     cout << "input pattern array initialized with min. len " << minLen << endl;\r
459     // initialize the output pattern    \r
460     char** outputPattern = NULL;\r
461     outputPattern = new char*[nbProducingPorts];\r
462     int lengthOP = 0;\r
463     idIface = 0;\r
464     foreach(AbstractInterface* iface, getControlOutputs()) {\r
465       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
466       lengthOP = minLen+connIface->getProductionPattern().size();\r
467       outputPattern[idIface] = new char[lengthOP];\r
468       memset(outputPattern[idIface],0,lengthOP);\r
469       idIface += 1;\r
470     }\r
471     cout << "output pattern array initialized" << endl;\r
472     \r
473     int clock = 0;\r
474     nbExec = 0;\r
475     // search for the beginning of the first execution.\r
476     while ((clock < minLen) && (! isValidDataGroup(inputPattern,nbConsumingPorts,clock))) clock++;\r
477     cout << "found 1st exec clock: " << clock << endl;\r
478     \r
479     while (clock < minLen) {\r
480       // initialize counters for current execution.\r
481       int p = 0; // index in production pattern\r
482       int o = 0; // clock+o will give the clock cycle of each output group\r
483       int cip = 0; // clock+cip give the clock cycle of an input group\r
484       int ccp = 0; // ccp give a column in the consumptio pattern\r
485       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
486       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
487       bool cannotCompleteExec = false;\r
488       for(int m=0;m<productionCounter.size();m++) {\r
489         // search for the first production in PP\r
490         while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {\r
491           p += 1;\r
492           o += 1;\r
493         }\r
494         int gap = 0; // count the number of extra null columns\r
495         // search for PC(m) valid input group in IP\r
496         while (nip < productionCounter.at(m)) {\r
497           if (clock+cip < minLen) {\r
498             if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;\r
499             cip += 1;\r
500             gap += 1;\r
501           }\r
502           else {\r
503             cannotCompleteExec = true;\r
504             break;\r
505           }        \r
506         }\r
507         \r
508         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
509         \r
510         // search for PC(m) valid input group in IP\r
511         while (ncp < productionCounter.at(m)) {\r
512           if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) ncp += 1;\r
513           ccp += 1;\r
514           gap -= 1;\r
515         }\r
516         o += gap; // to take into acocunt of extra null columns\r
517         combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);\r
518         p += 1;\r
519         o += 1;\r
520       }\r
521       \r
522       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
523       \r
524       // current exec. taken into accunt\r
525       nbExec += 1;\r
526       \r
527       // search for the next exec.\r
528       clock += 1;      \r
529       nip = 0;\r
530       while ((clock < minLen) && (nip < delta)) {\r
531         if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;\r
532         if (nip < delta) clock += 1;\r
533       }\r
534     }\r
535     // find the last valid output data group\r
536     while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;\r
537     \r
538     //for(int i=0;i<lengthOP;i++) cout << (int)(outputPattern[0][i]);\r
539     //cout << endl;\r
540     // copy back outputPattern info each interface\r
541     idIface = 0;\r
542     foreach(AbstractInterface* iface, getControlOutputs()) {\r
543       ConnectedInterface* connIface = AI_TO_CON(iface);\r
544       QList<char> pattern;\r
545       for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);\r
546       connIface->setOutputPattern(pattern);      \r
547       idIface += 1;\r
548     }\r
549     \r
550     // clear inputPattern and outputPattern\r
551     for(int i=0;i<nbConsumingPorts; i++) {\r
552       delete [] inputPattern[i];\r
553     }\r
554     delete [] inputPattern;\r
555     for(int i=0;i<nbProducingPorts; i++) {\r
556       delete [] outputPattern[i];\r
557     }\r
558     delete [] outputPattern;\r
559   }\r
560   return true;\r
561 }\r
562 \r
563 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
564   \r
565   for(int i=0;i<nbPorts;i++) {\r
566     if (pattern[i][clock] == 1) return true;\r
567   }\r
568   return false;  \r
569 }\r
570 \r
571 void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {\r
572   \r
573   for (int i=0;i<nbCols;i++) {\r
574     for(int j=0;j<nbPorts;j++) {\r
575       patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];\r
576     }\r
577   }\r
578   \r
579 }\r
580 \r
581 void FunctionalBlock::clearConsumptionPattern() {\r
582   if (consumptionPattern == NULL) return;\r
583   \r
584   for(int i=0;i<nbConsumingPorts; i++) {\r
585     delete [] consumptionPattern[i];\r
586   }\r
587   delete [] consumptionPattern;      \r
588 }\r
589 \r
590 void FunctionalBlock::clearProductionPattern() {\r
591   if (productionPattern == NULL) return;\r
592   for(int i=0;i<nbProducingPorts;i++) {\r
593     delete [] productionPattern[i];\r
594   }\r
595   delete [] productionPattern;\r
596 }\r
597 \r
598 void FunctionalBlock::initConsumptionPattern() {\r
599   static QString fctName = "FunctionalBlock::initConsumptionPattern()";\r
600 #ifdef DEBUG_FCTNAME\r
601   cout << "call to " << qPrintable(fctName) << endl;\r
602 #endif\r
603   \r
604   if (consumptionPattern != NULL) clearConsumptionPattern();\r
605   \r
606   nbConsumingPorts = getControlInputs().size();  \r
607   int idIface = 0;\r
608   consumptionPattern = new char*[nbConsumingPorts];  \r
609   foreach(AbstractInterface* iface, getControlInputs()) {\r
610     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
611     QList<char> in = connIface->getConsumptionPattern();\r
612     lengthCP = in.size(); // normally, all inputs have the same lenght for CP\r
613     consumptionPattern[idIface] = new char[lengthCP];\r
614     int i = 0;\r
615     foreach(char c, in) consumptionPattern[idIface][i++] = c;\r
616     idIface += 1;    \r
617   }\r
618 }\r
619 \r
620 void FunctionalBlock::initProductionPattern() {\r
621   static QString fctName = "FunctionalBlock::initProductionPattern()";\r
622 #ifdef DEBUG_FCTNAME\r
623   cout << "call to " << qPrintable(fctName) << endl;\r
624 #endif\r
625   \r
626   if (productionPattern != NULL) clearProductionPattern();\r
627   \r
628   nbProducingPorts = getControlOutputs().size();  \r
629   int idIface = 0;\r
630   productionPattern = new char*[nbProducingPorts];  \r
631   foreach(AbstractInterface* iface, getControlOutputs()) {\r
632     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
633     QList<char> in = connIface->getProductionPattern();\r
634     lengthPP = in.size(); // normally, all inputs have the same lenght for PP\r
635     productionPattern[idIface] = new char[lengthPP];\r
636     int i = 0;\r
637     foreach(char c, in) productionPattern[idIface][i++] = c;\r
638     idIface += 1;    \r
639   }\r
640 }\r