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

Private GIT Repository
b4947840a6b8b16a41ad03edd47586cbbbc1291a
[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   cout << "PP of " << qPrintable(name) << endl;\r
147   QMapIterator<AbstractInterface*,QList<char>* > it(productionPattern);\r
148   while (it.hasNext()) {\r
149     it.next();\r
150     QList<char>* pat = it.value();\r
151     foreach(char c, *pat) cout << (int)c;\r
152     cout << endl;\r
153   }\r
154 }\r
155 \r
156 void FunctionalBlock::createDelta() throw(Exception) {\r
157   static QString fctName = "FunctionalBlock::createDelta()";\r
158 #ifdef DEBUG_FCTNAME\r
159   cout << "call to " << qPrintable(fctName) << endl;\r
160 #endif \r
161   \r
162   QString deltaStr = implementation->getDelta();  \r
163   cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;\r
164   if (deltaStr.isEmpty()) {\r
165     delta = -1;\r
166     return;\r
167   }\r
168   \r
169   // look for parameter names  \r
170   double result = 0;\r
171   try {\r
172     result = evaluateExpression(deltaStr);\r
173   }\r
174   catch(Exception e) {\r
175     throw(e);\r
176   }\r
177   delta = result;\r
178   cout << "delta = " << delta << endl;\r
179 }\r
180 \r
181 void FunctionalBlock::createConsumptionPattern()  throw(Exception) {\r
182   static QString fctName = "FunctionalBlock::createConsumptionPattern()";\r
183 #ifdef DEBUG_FCTNAME\r
184   cout << "call to " << qPrintable(fctName) << endl;\r
185 #endif\r
186   \r
187   // first clear if already exists\r
188   clearConsumptionPattern();\r
189 \r
190   lengthCP = -1;  \r
191   QHash<QString,QString> consPattern = implementation->getConsumptionPattern();  \r
192   \r
193   foreach(AbstractInterface* iface, getControlInputs()) {       \r
194     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
195     QString refName = connIface->getReference()->getName();    \r
196     if (! consPattern.contains(refName)) {\r
197       throw(Exception(NO_IFACE_CP,this));\r
198       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;\r
199     }\r
200     QList<char>* pattern = NULL;\r
201     try {\r
202       pattern = expandPattern(consPattern.value(refName));\r
203     }\r
204     catch(Exception e) {\r
205       throw(e);\r
206     }\r
207     consumptionPattern.insert(connIface,pattern);\r
208     if (lengthCP == -1) {\r
209       lengthCP = pattern->size();\r
210     }\r
211     else {\r
212       if (pattern->size() != lengthCP) {\r
213         throw(Exception(INVALID_IFACE_CP_LENGTH,this));\r
214       }\r
215     }\r
216   }          \r
217 }\r
218 \r
219 void FunctionalBlock::createProductionPattern() throw(Exception){  \r
220   static QString fctName = "FunctionalBlock::createProductionPattern()";\r
221 #ifdef DEBUG_FCTNAME\r
222   cout << "call to " << qPrintable(fctName) << endl;\r
223 #endif\r
224 \r
225   // first clear if already exists\r
226   clearProductionPattern();\r
227   \r
228   lengthPP = -1;  \r
229   QHash<QString,QString> prodPattern = implementation->getProductionPattern();  \r
230   \r
231   foreach(AbstractInterface* iface, getControlOutputs()) {    \r
232     FunctionalInterface* connIface = AI_TO_FUN(iface);\r
233     QString refName = connIface->getReference()->getName();    \r
234     if (! prodPattern.contains(refName)) {\r
235       throw(Exception(NO_IFACE_PP,this));\r
236     }\r
237     QList<char>* pattern = NULL;\r
238     try {\r
239       pattern = expandPattern(prodPattern.value(refName));\r
240     }\r
241     catch(Exception e) {\r
242       throw(e);\r
243     }\r
244     productionPattern.insert(connIface,pattern);\r
245     if (lengthPP == -1) {\r
246       lengthPP = pattern->size();\r
247     }\r
248     else {\r
249       if (pattern->size() != lengthPP) {\r
250         throw(Exception(INVALID_IFACE_PP_LENGTH,this));\r
251       }\r
252     }\r
253   }      \r
254 }\r
255 \r
256 void FunctionalBlock::createProductionCounter() throw(Exception) {\r
257   static QString fctName = "FunctionalBlock::createProductionCounter()";\r
258 #ifdef DEBUG_FCTNAME\r
259   cout << "call to " << qPrintable(fctName) << endl;\r
260 #endif\r
261 \r
262   // first clear if already exists\r
263   productionCounter.clear();\r
264 \r
265   \r
266   QStringList counterParts = implementation->getProductionCounter().split(",");\r
267   foreach(QString s, counterParts) {\r
268     cout << "cont part = " << qPrintable(s) << endl;\r
269     bool ok;\r
270     double val = s.toDouble(&ok);\r
271     if (ok) {\r
272       productionCounter.append(val);\r
273     }\r
274     else if (s.at(0) == '{') {\r
275       s.remove(0,1);\r
276       s.chop(1);\r
277       QStringList gen = s.split(":");\r
278       if (gen.size() != 3) {\r
279         throw(Exception(INVALID_IFACE_PC,this));\r
280       }\r
281       int start = 0;\r
282       int nb = 0;\r
283       int step = 0;\r
284       for(int i=0;i<3;i++) {        \r
285         double result = 0.0;\r
286         try {\r
287           result = evaluateExpression(gen.at(i));\r
288         }\r
289         catch(Exception e) {\r
290           throw(e);\r
291         }\r
292         if (i==0) start = result;\r
293         else if (i==1) nb = result;\r
294         else if (i==2) step = result;\r
295       }\r
296       for(int j=0;j<nb;j++) {\r
297         productionCounter.append(start+j*step);\r
298       }\r
299     }\r
300     else {      \r
301       double result = 0.0;\r
302       try {\r
303         result = evaluateExpression(s);\r
304       }\r
305       catch(Exception e) {\r
306         throw(e);\r
307       }\r
308       productionCounter.append(result);      \r
309     }\r
310   }\r
311   foreach(int val, productionCounter) {\r
312     cout << val << ",";\r
313   }\r
314   cout << endl;\r
315 }\r
316 \r
317 QList<char>* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exception) {\r
318   static QString fctName = "FunctionalBlock::expandPattern()";\r
319 #ifdef DEBUG_FCTNAME\r
320   cout << "call to " << qPrintable(fctName) << endl;\r
321 #endif\r
322   /* expanding a pattern is done in two steps :\r
323       - 1 : finding all variables that correspond to an expression\r
324             and copy them in the pattern\r
325       - 2 : parsing the result\r
326 \r
327       Note that the result MUST contain only variables that have a\r
328       integer/double value. Otherwise, expanding will fail.\r
329 \r
330    */\r
331 \r
332   // first step.\r
333 \r
334   QString p = replaceExpressions(patternIn);\r
335 \r
336   QList<char> lst;  \r
337   p.append(')');\r
338   int offset = 0;  \r
339   QList<char>* patternOut = new QList<char>();\r
340   try {\r
341     patternOut->append(expandPatternRecur(p,&offset));\r
342   }\r
343   catch(Exception e) {\r
344     throw(e);\r
345   }\r
346 \r
347   return patternOut;\r
348 }\r
349 \r
350 QString FunctionalBlock::replaceExpressions(const QString& patternIn) throw(Exception) {\r
351 \r
352   QString res = patternIn;\r
353   bool stop = false;\r
354   QRegularExpression re("[$][a-zA-Z0-9_]+");\r
355 \r
356   while (!stop) {\r
357     stop = true;\r
358     QRegularExpressionMatchIterator matcher = re.globalMatch(res);\r
359     while(matcher.hasNext()) {\r
360       QRegularExpressionMatch m = matcher.next();\r
361       QString param = m.captured(0);\r
362       QString paramName = param;\r
363       paramName.remove(0,1);\r
364       BlockParameter* p = getParameterFromName(paramName);\r
365       if ((p != NULL) && (p->getType() == BlockParameter::Expression)) {\r
366         res.replace(param,p->getStringValue());\r
367         stop = false;\r
368         cout << "found an expr: " << qPrintable(paramName) << ", patern => " << qPrintable(res) << endl;\r
369       }\r
370     }\r
371   }\r
372   return res;\r
373 }\r
374 \r
375 QList<char> FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset) throw(Exception) {\r
376   \r
377   QList<char> patternOut;\r
378 \r
379   while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) {\r
380     \r
381     QChar c = patternIn.at(*offset);\r
382     if (c == '(') {\r
383       *offset += 1;\r
384       try {\r
385         patternOut.append(expandPatternRecur(patternIn,offset));\r
386       }\r
387       catch(Exception e) {\r
388         throw(e);\r
389       }\r
390     }\r
391     else if (c == '0') {\r
392       patternOut.append(0);\r
393     }\r
394     else if (c == '1') {\r
395       patternOut.append(1);\r
396     }\r
397     else if (c == 'X') {\r
398       patternOut.append(-1);\r
399     }\r
400     else if (c == '{') {\r
401       *offset += 1;\r
402       QString expr = "";      \r
403       while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {\r
404         expr += patternIn.at(*offset);        \r
405         *offset += 1;\r
406       }\r
407       if (*offset == patternIn.size()) {\r
408         throw(Exception(INVALID_IFACE_PATTERN,this));\r
409       }\r
410       double repeat = 0;\r
411       try {\r
412         repeat = evaluateExpression(expr);\r
413       }\r
414       catch(Exception e) {\r
415         throw(e);\r
416       }\r
417       // repeat just the last value in currentGroup\r
418       char last = patternOut.last();\r
419       //cout << "repeat last char " << repeat << " times : " << (int)last << endl;\r
420       \r
421       for(int i=1;i<(int)repeat;i++) {\r
422         patternOut.append(last);\r
423       }\r
424     }    \r
425     *offset += 1;\r
426   }\r
427   \r
428   // must check if after ), there is a {\r
429   if ((*offset < patternIn.size()-1) && (patternIn.at(*offset+1) == '{')) {\r
430     *offset += 2;\r
431     QString expr = "";      \r
432     while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {\r
433       expr += patternIn.at(*offset);        \r
434       *offset += 1;\r
435     }\r
436     if (*offset == patternIn.size()) {\r
437       throw(Exception(INVALID_IFACE_PATTERN,this));\r
438     }\r
439     double repeat = 0;\r
440     try {\r
441       repeat = evaluateExpression(expr);\r
442     }\r
443     catch(Exception e) {\r
444       throw(e);\r
445     }\r
446     /*\r
447     cout << "repeat last group " << repeat << " times : ";\r
448     foreach (char c, currentGroup) cout <<(int)c;\r
449     cout << endl;  \r
450     */\r
451     QList<char> single = patternOut;\r
452     for(int i=1;i<(int)repeat;i++) {\r
453       patternOut.append(single);\r
454     }    \r
455   }  \r
456   return patternOut;\r
457 }\r
458 \r
459 double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exception) {\r
460   static QString fctName = "FunctionalBlock::evaluateExpression()";\r
461 #ifdef DEBUG_FCTNAME\r
462   cout << "call to " << qPrintable(fctName) << endl;\r
463 #endif\r
464     \r
465   QHash<QString,double> vars;\r
466   evaluator->setExpression(expression);\r
467   QList<QString> varNames = evaluator->getVariableNames();\r
468   foreach (QString name, varNames) {\r
469     QString paramName = name;\r
470     paramName.remove(0,1);\r
471     BlockParameter* param = getParameterFromName(paramName);\r
472     if (param == NULL) {\r
473       throw(Exception(EVAL_PARAM_UNKNOWN,this));\r
474     }\r
475     bool okVal;\r
476     int val = param->getDoubleValue(&okVal);    \r
477     if (!okVal) {\r
478       throw(Exception(EVAL_PARAM_NOVALUE,this));\r
479     }\r
480     vars.insert(name,(double)val);    \r
481   }\r
482   \r
483   evaluator->setVariablesValue(vars);\r
484   double result = 0.0;\r
485   try {\r
486     result = evaluator->evaluate();\r
487   }\r
488   catch(int index) {\r
489     cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;\r
490     throw(Exception(EVAL_INVALID_EXPR,this));\r
491   }\r
492   return result;\r
493 }\r
494 \r
495 void FunctionalBlock::computeAdmittanceDelays() throw(Exception) {\r
496   static QString fctName = "FunctionalBlock::computeAdmittanceDelays()";\r
497 #ifdef DEBUG_FCTNAME\r
498   cout << "call to " << qPrintable(fctName) << endl;\r
499 #endif\r
500   QList<int> inClock;\r
501   QList<int> delays;\r
502 \r
503   clearAdmittanceDelays();\r
504 \r
505   // trying to synchronize the first one in AP\r
506   QMapIterator<AbstractInterface*,QList<char>* > iterAP(admittance);\r
507   QMapIterator<AbstractInterface*,QList<char>* > iterIP(inputPattern);\r
508 \r
509   while (iterAP.hasNext()) {\r
510     iterAP.next();\r
511     iterIP.next();\r
512     QList<char>* ap = iterAP.value();\r
513     QList<char>* ip = iterIP.value();\r
514     int first = 0;\r
515     while ((first < lengthIP) && (ip->at(first) == 0)) first++;\r
516     while ((first < lengthAP) && (ap->at(first) == 0)) first--;\r
517     delays.append(first);\r
518     inClock.append(0);\r
519     QList<int>* delays = new QList<int>();\r
520     admittanceDelays.insert(iterAP.key(), delays);\r
521   }\r
522 \r
523   QMapIterator<AbstractInterface*,QList<int>* > iterDelays(admittanceDelays);\r
524 \r
525   // get the delay to apply\r
526   int maxDelay = 0;\r
527   for(int i=0;i<delays.size();i++) {\r
528     if (delays[i] > maxDelay) maxDelay = delays[i];\r
529   }\r
530   // adding the delays to IP\r
531   iterIP.toFront();\r
532   int i = 0;\r
533   while (iterIP.hasNext()) {\r
534     iterIP.next();\r
535     iterDelays.next();\r
536     QList<char>* ip = iterIP.value();\r
537     QList<int>* d = iterDelays.value();\r
538     d->append(maxDelay-delays[i]);\r
539     cout << "prependind " << qPrintable(iterIP.key()->getName()) << " with " << (maxDelay-delays[i]) << " 0" << endl;\r
540     for(int j=0;j<maxDelay-delays[i];j++) {\r
541       ip->prepend(0);\r
542     }\r
543     for(int j=0;j<delays[i];j++) {\r
544       ip->append(0);\r
545     }\r
546     i++;\r
547   }\r
548   lengthIP += maxDelay;\r
549 \r
550   cout << "IP length = " << lengthIP << ", AP length = " << lengthAP << endl;\r
551   bool stop = false;\r
552   int apIndex = 0;\r
553   int ipIndex = 0;\r
554   while (!stop) {\r
555 \r
556     // if AP is a valid group, search for the next valid group in IP\r
557     if (isValidDataGroup(admittance,apIndex)) {\r
558 \r
559       while ((ipIndex < lengthIP) && (! isValidDataGroup(inputPattern,ipIndex))) ipIndex++;\r
560       if (ipIndex == lengthIP) {\r
561         stop = true;\r
562         continue;\r
563       }\r
564     }\r
565 \r
566     iterAP.toFront();\r
567     iterIP.toFront();\r
568     iterDelays.toFront();\r
569 \r
570     if (samePatterns(inputPattern,ipIndex,admittance,apIndex)) {\r
571       while (iterAP.hasNext()) {\r
572         iterAP.next();\r
573         iterDelays.next();\r
574         QList<char>* ap = iterAP.value();\r
575         if (ap->at(apIndex) == 1) {\r
576           QList<int>* d = iterDelays.value();\r
577           d->append(0); // the 1 is at its good place, so no delay\r
578         }\r
579       }\r
580     }\r
581     else {\r
582       cout << "diff between IP and AP at " << apIndex << endl;\r
583       // search for the next 1 in IP for every input that has a 1 in AP\r
584 \r
585       while (iterAP.hasNext()) {\r
586         iterAP.next();\r
587         iterIP.next();\r
588         iterDelays.next();\r
589         QList<char>* ap = iterAP.value();\r
590         QList<char>* ip = iterIP.value();\r
591         QList<int>* d = iterDelays.value();\r
592         // case 1: 1 in IP is too late\r
593         if ((ap->at(apIndex) == 1) && (ip->at(ipIndex) == 0)) {\r
594           int delay = 1;\r
595           while ( ((ipIndex+delay) < lengthIP) && (ip->at(ipIndex+delay) == 0) ) delay++;\r
596           cout << "found a delay of " << (-delay) << " for iface " << qPrintable(iterAP.key()->getName()) << endl;\r
597           // moving the 1 to its normal pos.\r
598           ip->replace(ipIndex,1);\r
599           ip->replace(ipIndex+delay,0);\r
600           d->append(-delay);\r
601         }\r
602         // case 2: 1 in IP is too soon\r
603         else if ((ap->at(apIndex) == 0) && (ip->at(ipIndex) == 1)) {\r
604           int delay = 1;\r
605           while ( ((apIndex+delay) < lengthAP) && (ap->at(apIndex+delay) == 0) ) delay++;\r
606           cout << "found a delay of " << delay << " for iface " << qPrintable(iterAP.key()->getName()) << endl;\r
607           // search for next 0 in IP to put the 1\r
608           int k = ipIndex+delay;\r
609           while ((k < lengthIP) && (ip->at(k) == 1)) k++;\r
610           ip->replace(ipIndex,0);\r
611           ip->replace(k,1);\r
612           d->append(delay);\r
613         }\r
614       }\r
615       if (! samePatterns(inputPattern,inClock,admittance,apIndex)) {\r
616          cout << "Abnormal case while searching for delays" << endl;\r
617       }\r
618     }\r
619 \r
620     apIndex++;\r
621     ipIndex++;\r
622     if ((apIndex >= lengthAP) || (ipIndex >= lengthIP)) stop = true;\r
623   }\r
624   iterDelays.toFront();\r
625   while (iterDelays.hasNext()) {\r
626     iterDelays.next();\r
627     QList<int>* d = iterDelays.value();\r
628     foreach(int v, *d) {\r
629       cout << v << " ";\r
630     }\r
631     cout << endl;\r
632   }\r
633 \r
634 }\r
635 \r
636 void FunctionalBlock::createInputPattern()  throw(Exception) {\r
637   static QString fctName = "FunctionalBlock::createInputPattern())";\r
638 #ifdef DEBUG_FCTNAME\r
639   cout << "call to " << qPrintable(fctName) << endl;\r
640 #endif\r
641   \r
642   lengthIP = -1;\r
643   foreach(AbstractInterface* iface, getControlInputs()) {\r
644 \r
645     ConnectedInterface* connIface = AI_TO_CON(iface);\r
646     // check if it is connected\r
647     if (connIface->getConnectedFrom() == NULL) {\r
648       throw(Exception(IFACE_NOT_CONNECTED,this));\r
649     }\r
650     // get the precursor output pattern\r
651     QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();\r
652     AbstractInputModifier* modifier = connIface->getInputModifier();\r
653     // check if the input is modified\r
654     if (modifier != NULL) {\r
655 \r
656       out = modifier->getModifiedInput(out);\r
657     }\r
658 \r
659     if (out->size() == 0) {\r
660       clearInputPattern();\r
661       throw(Exception(NO_IFACE_IP,this));\r
662     }\r
663     if (lengthIP == -1) {\r
664       lengthIP = out->size();\r
665     }\r
666     else {\r
667       if (out->size() < lengthIP) lengthIP = out->size();\r
668     }\r
669     \r
670     QList<char>* in = new QList<char>(*out);\r
671     foreach(char c, *in) {\r
672       cout << (int)c;\r
673     }\r
674     cout << endl;    \r
675     inputPattern.insert(connIface,in);    \r
676   }\r
677   // search the last valid group in IP,\r
678   while(! isValidDataGroup(inputPattern,lengthIP-1)) {\r
679     //removeDataGroup(inputPattern,lengthIP-1);\r
680     lengthIP -= 1;\r
681   }\r
682 }\r
683 \r
684 void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) {\r
685   static QString fctName = "FunctionalBlock::createAdmittance()";\r
686 #ifdef DEBUG_FCTNAME\r
687   cout << "call to " << qPrintable(fctName) << endl;\r
688 #endif  \r
689   // firstly, copy CP in AP\r
690   QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);\r
691   while (iterC.hasNext()) {\r
692     iterC.next();\r
693     QList<char>* pattern = new QList<char>(*(iterC.value()));\r
694     admittance.insert(iterC.key(), pattern);    \r
695   }\r
696   lengthAP = lengthCP;\r
697   int clock = 0;  \r
698   cout << "trigger 1 at c.c. 0" << endl;\r
699   for(int i=1;i<nbExec;i++) {\r
700     // searching for the clock cycle for which a new exec starts\r
701     int nbGroup = 0;\r
702     while ((clock < lengthAP) && (nbGroup < delta)) {\r
703       if (isValidDataGroup(admittance,clock)) nbGroup+=1;\r
704       clock += 1;\r
705     }\r
706     while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;\r
707     cout << "trigger " << (i+1) << " at c.c. " << clock << endl;\r
708     int sc = clock;\r
709     // combine CP with AP at sc\r
710     for(int j=0;j<lengthCP;j++) {\r
711       // first case : column of CP must be placed beyond AP's end.\r
712       if (sc == lengthAP) {\r
713         cout << i << "," << j << " append in AP at " << sc << endl;\r
714         appendToPattern(consumptionPattern,j,admittance,1);\r
715         lengthAP += 1;\r
716         sc += 1;               \r
717       }\r
718       // second case : CP and AP can be combined directly (i.e. no X | 1 to do)\r
719       else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
720         cout << i << "," << j << " combine at " << sc << endl;\r
721         combinePatterns(consumptionPattern,j,admittance,sc);\r
722         sc += 1;\r
723       }\r
724       // third case : CP has an X column\r
725       else if (isOnlyXDataGroup(consumptionPattern,j)) {\r
726         cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;\r
727         shiftRightPattern(admittance,sc);\r
728         lengthAP += 1;\r
729         if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
730           cerr << "Abnormal case when combining AP and CP" << endl;\r
731         }\r
732         combinePatterns(consumptionPattern,j,admittance,sc);        \r
733         sc += 1;\r
734       }\r
735       // fourth case : AP has an X column\r
736       else if (isOnlyXDataGroup(admittance,sc)) {\r
737         cout << i << "," << j << " jump c.c. for CP at " << sc << endl;        \r
738         sc += 1;\r
739         j -= 1;\r
740       }\r
741       else {\r
742         throw(INVALID_DELTA_CP);        \r
743       }\r
744     }\r
745   }\r
746   // turn all X into 0\r
747   QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);\r
748   while (iterA.hasNext()) {\r
749     iterA.next();\r
750     QList<char>* pattern = iterA.value();\r
751     for(int i=0;i<pattern->size();i++) {\r
752       if (pattern->at(i) == -1) pattern->replace(i,0);\r
753       cout << (int)(pattern->at(i));\r
754     }\r
755     cout << endl;\r
756   }  \r
757 }\r
758 \r
759 void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) {\r
760   static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
761 #ifdef DEBUG_FCTNAME\r
762   cout << "call to " << qPrintable(fctName) << endl;\r
763 #endif\r
764     \r
765   // firstly, create input pattern\r
766   try {\r
767     createInputPattern();\r
768   }\r
769   catch(Exception e) {\r
770     throw(e);\r
771   }\r
772   int nbExec = createTriggers();\r
773   cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;\r
774   \r
775   try {\r
776     createAdmittance(nbExec);\r
777   }\r
778   catch(Exception e) {\r
779     cout << "cannot create admittance" << endl;\r
780     throw(e);\r
781   }\r
782   \r
783   int clock = 0; // index in IP  \r
784   int i = 0; // index in AP  \r
785   while ((clock < lengthIP) && (i < lengthAP)) {\r
786      \r
787     // if AP is a valid group, search for the next valid group in IP\r
788     if (isValidDataGroup(admittance,i)) {\r
789       while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
790       if (clock == lengthIP) {\r
791         cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;\r
792         throw(Exception(IP_END_NULLCOL,this));\r
793       }\r
794     }    \r
795     /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or\r
796        are both null columns\r
797     */\r
798     if (! samePatterns(inputPattern,clock,admittance,i)) {\r
799       cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;\r
800       throw(Exception(IP_AP_NOTCOMPAT,this)); // IP and AP not compatible\r
801     }\r
802     clock++;\r
803     i++;\r
804   }\r
805   if (clock < lengthIP) {\r
806     throw(Exception(AP_TOO_SHORT,this));\r
807     cerr << "Abnormal case: AP is to short" << endl;   \r
808   }  \r
809 }\r
810 \r
811 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {\r
812   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
813 #ifdef DEBUG_FCTNAME\r
814   cout << "call to " << qPrintable(fctName) << endl;\r
815 #endif\r
816 \r
817   clearOutputPattern();\r
818 \r
819   /* case 1: the block is a generator for which output pattern\r
820      must be computed for a nbExec following executions\r
821   */\r
822 \r
823   if (nbExec > 0) {\r
824     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
825     foreach(AbstractInterface* iface, getControlOutputs()) {\r
826       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
827       // create output pattern\r
828       QList<char>* pp = productionPattern.value(connIface);\r
829       QList<char>* pattern = new QList<char>(*pp);\r
830       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
831       // assign pattern to interface\r
832       connIface->setOutputPattern(pattern);\r
833       // store it in QMap\r
834       outputPattern.insert(connIface,pattern);      \r
835     }\r
836   }\r
837   else {\r
838     cout << "computing output pattern of " << qPrintable(name) << endl;\r
839     \r
840     // in case of inputPattern not created, do it\r
841     if (lengthIP <= 0) {\r
842 \r
843       cout << "Strange case: input pattern is not created while it is time to compute output pattern !" << endl;\r
844       // collect the input patterns for each input    \r
845       try {\r
846         createInputPattern();\r
847       }\r
848       catch(Exception e) {\r
849         throw(e);\r
850       }\r
851       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
852     }\r
853     \r
854     // initialize the output pattern    \r
855     lengthOP = 0;\r
856     foreach(AbstractInterface* iface, getControlOutputs()) {\r
857       FunctionalInterface* connIface = AI_TO_FUN(iface);      \r
858       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
859       QList<char>* pattern = new QList<char>();\r
860       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
861       connIface->setOutputPattern(pattern);\r
862       outputPattern.insert(connIface,pattern);\r
863     }\r
864     cout << "output pattern array initialized" << endl;\r
865     \r
866     int clock = 0;\r
867     nbExec = 0;\r
868     // search for the beginning of the first execution.\r
869     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
870     cout << "found 1st exec clock: " << clock << endl;\r
871     \r
872     while (clock < lengthIP) {\r
873       // initialize counters for current execution.\r
874       int p = 0; // index in production pattern\r
875       int o = 0; // clock+o will give the clock cycle of each output group\r
876       int cip = 0; // clock+cip give the clock cycle of an input group\r
877       int ccp = 0; // ccp give a column in the consumptio pattern\r
878       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
879       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
880       bool cannotCompleteExec = false;\r
881       for(int m=0;m<productionCounter.size();m++) {\r
882         // search for the first production in PP\r
883         while (!isValidDataGroup(productionPattern,p)) {\r
884           p += 1;\r
885           o += 1;\r
886         }\r
887         int gap = 0; // count the number of extra null columns\r
888         // search for PC(m) valid input group in IP\r
889         while (nip < productionCounter.at(m)) {\r
890           if (clock+cip < lengthIP) {\r
891             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
892             cip += 1;\r
893             gap += 1;\r
894           }\r
895           else {\r
896             cannotCompleteExec = true;\r
897             break;\r
898           }        \r
899         }        \r
900         \r
901         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
902         \r
903         // search for PC(m) valid input group in IP\r
904         while (ncp < productionCounter.at(m)) {\r
905           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
906           ccp += 1;\r
907           gap -= 1;\r
908         }\r
909         o += gap; // to take into acocunt of extra null columns\r
910         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
911         p += 1;\r
912         o += 1;\r
913       }\r
914       \r
915       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
916       \r
917       // current exec. taken into accunt\r
918       nbExec += 1;\r
919       \r
920       // search for the next exec.\r
921       clock += 1;      \r
922       nip = 0;\r
923       while ((clock < lengthIP) && (nip < delta)) {\r
924         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
925         if (nip < delta) clock += 1;\r
926       }\r
927       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
928     }\r
929     // find the last valid output data group\r
930     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
931       removeDataGroup(outputPattern,lengthOP-1);\r
932       lengthOP -= 1;\r
933     }\r
934 \r
935     // clear input pattern\r
936     clearInputPattern();\r
937   }  \r
938 }\r
939 \r
940 /*\r
941 \r
942 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {\r
943   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
944 #ifdef DEBUG_FCTNAME\r
945   cout << "call to " << qPrintable(fctName) << endl;\r
946 #endif\r
947 \r
948   // case 1: the block is a generator for which output pattern\r
949   //   must be computed for a nbExec following executions\r
950 \r
951   if (nbExec > 0) {\r
952     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
953     foreach(AbstractInterface* iface, getControlOutputs()) {\r
954       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
955       // create output pattern\r
956       QList<char>* pp = productionPattern.value(connIface);\r
957       QList<char>* pattern = new QList<char>(*pp);\r
958       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
959       // assign pattern to interface\r
960       connIface->setOutputPattern(pattern);\r
961       // store it in QMap\r
962       outputPattern.insert(connIface,pattern);\r
963     }\r
964   }\r
965   else {\r
966     cout << "computing output pattern of " << qPrintable(name) << endl;\r
967 \r
968     // in case of inputPattern not created, do it\r
969     if (lengthIP <= 0) {\r
970       // collect the input patterns for each input\r
971       try {\r
972         createInputPattern();\r
973       }\r
974       catch(Exception e) {\r
975         throw(e);\r
976       }\r
977       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
978     }\r
979 \r
980     // initialize the output pattern\r
981     lengthOP = 0;\r
982     foreach(AbstractInterface* iface, getControlOutputs()) {\r
983       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
984       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
985       QList<char>* pattern = new QList<char>();\r
986       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
987       connIface->setOutputPattern(pattern);\r
988       outputPattern.insert(connIface,pattern);\r
989     }\r
990     cout << "output pattern array initialized" << endl;\r
991 \r
992     int clock = 0;\r
993     nbExec = 0;\r
994     // search for the beginning of the first execution.\r
995     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
996     cout << "found 1st exec clock: " << clock << endl;\r
997 \r
998     while (clock < lengthIP) {\r
999       // initialize counters for current execution.\r
1000       int p = 0; // index in production pattern\r
1001       int o = 0; // clock+o will give the clock cycle of each output group\r
1002       int cip = 0; // clock+cip give the clock cycle of an input group\r
1003       int ccp = 0; // ccp give a column in the consumptio pattern\r
1004       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
1005       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
1006       bool cannotCompleteExec = false;\r
1007       for(int m=0;m<productionCounter.size();m++) {\r
1008         // search for the first production in PP\r
1009         while (!isValidDataGroup(productionPattern,p)) {\r
1010           p += 1;\r
1011           o += 1;\r
1012         }\r
1013         int gap = 0; // count the number of extra null columns\r
1014         // search for PC(m) valid input group in IP\r
1015         while (nip < productionCounter.at(m)) {\r
1016           if (clock+cip < lengthIP) {\r
1017             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
1018             cip += 1;\r
1019             gap += 1;\r
1020           }\r
1021           else {\r
1022             cannotCompleteExec = true;\r
1023             break;\r
1024           }\r
1025         }\r
1026 \r
1027         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
1028 \r
1029         // search for PC(m) valid input group in IP\r
1030         while (ncp < productionCounter.at(m)) {\r
1031           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
1032           ccp += 1;\r
1033           gap -= 1;\r
1034         }\r
1035         o += gap; // to take into acocunt of extra null columns\r
1036         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
1037         p += 1;\r
1038         o += 1;\r
1039       }\r
1040 \r
1041       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
1042 \r
1043       // current exec. taken into accunt\r
1044       nbExec += 1;\r
1045 \r
1046       // search for the next exec.\r
1047       clock += 1;\r
1048       nip = 0;\r
1049       while ((clock < lengthIP) && (nip < delta)) {\r
1050         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
1051         if (nip < delta) clock += 1;\r
1052       }\r
1053       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
1054     }\r
1055     // find the last valid output data group\r
1056     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
1057       removeDataGroup(outputPattern,lengthOP-1);\r
1058       lengthOP -= 1;\r
1059     }\r
1060 \r
1061     // clear input pattern\r
1062     clearInputPattern();\r
1063   }\r
1064 }\r
1065 */\r
1066 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
1067   \r
1068   if (patternSrc.size() != patternDest.size()) return false;\r
1069   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1070   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1071   while (iterSrc.hasNext()) {\r
1072     iterSrc.next();\r
1073     iterDest.next();    \r
1074     QList<char>* srcPat = iterSrc.value();\r
1075     QList<char>* destPat = iterDest.value();\r
1076     if (srcCol >= srcPat->size()) return false;\r
1077     if (destCol >= destPat->size()) return false;\r
1078     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;    \r
1079   }\r
1080   return true;\r
1081 }\r
1082 \r
1083 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, const QList<int> &srcCols, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
1084   if (patternSrc.size() != srcCols.size()) return false;\r
1085   if (patternSrc.size() != patternDest.size()) return false;\r
1086 \r
1087   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1088   QListIterator<int> iterSrcCol(srcCols);\r
1089   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1090   while (iterSrc.hasNext()) {\r
1091     iterSrc.next();\r
1092     int srcCol = iterSrcCol.next();\r
1093     iterDest.next();\r
1094     QList<char>* srcPat = iterSrc.value();\r
1095     QList<char>* destPat = iterDest.value();\r
1096     if (srcCol >= srcPat->size()) return false;\r
1097     if (destCol >= destPat->size()) return false;\r
1098     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;\r
1099   }\r
1100   return true;\r
1101 }\r
1102 \r
1103 bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
1104   if (patternSrc.size() != patternDest.size()) return false;\r
1105   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1106   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1107   while (iterSrc.hasNext()) {\r
1108     iterSrc.next();\r
1109     iterDest.next();    \r
1110     QList<char>* srcPat = iterSrc.value();\r
1111     QList<char>* destPat = iterDest.value();\r
1112     if (srcCol >= srcPat->size()) return false;\r
1113     if (destCol >= destPat->size()) return false;\r
1114     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;\r
1115     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;\r
1116   }\r
1117   return true;\r
1118 }\r
1119 \r
1120 void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
1121   if (patternSrc.size() != patternDest.size()) return;\r
1122   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1123   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1124   while (iterSrc.hasNext()) {\r
1125     iterSrc.next();\r
1126     iterDest.next();    \r
1127     QList<char>* srcPat = iterSrc.value();\r
1128     QList<char>* destPat = iterDest.value();\r
1129     if (srcCol >= srcPat->size()) return;\r
1130     if (destCol >= destPat->size()) return;\r
1131     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;\r
1132     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;    \r
1133     destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));\r
1134   }  \r
1135 }\r
1136 \r
1137 void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {\r
1138   if (patternSrc.size() != patternDest.size()) return;\r
1139   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1140   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1141   while (iterSrc.hasNext()) {\r
1142     iterSrc.next();\r
1143     iterDest.next();    \r
1144     QList<char>* srcPat = iterSrc.value();\r
1145     QList<char>* destPat = iterDest.value();    \r
1146     int i=0;\r
1147     while ((srcCol+i < srcPat->size()) && (i<nbCols)) {\r
1148       destPat->append(srcPat->at(srcCol+i));\r
1149       i++;\r
1150     }\r
1151   }  \r
1152 }\r
1153 \r
1154 void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1155   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1156   while (iterSrc.hasNext()) {\r
1157     iterSrc.next();    \r
1158     QList<char>* srcPat = iterSrc.value();\r
1159     if (offset < srcPat->size()) {\r
1160       srcPat->removeAt(offset);\r
1161     }\r
1162   }\r
1163 }\r
1164 \r
1165 void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1166   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1167   while (iterSrc.hasNext()) {\r
1168     iterSrc.next();    \r
1169     QList<char>* srcPat = iterSrc.value();\r
1170     if (offset < srcPat->size()) {\r
1171       srcPat->insert(offset,0);\r
1172     }\r
1173   }\r
1174 }\r
1175 \r
1176 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1177   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1178   while (iterSrc.hasNext()) {\r
1179     iterSrc.next();    \r
1180     QList<char>* srcPat = iterSrc.value();\r
1181     if (offset >= srcPat->size()) return false;\r
1182     if (srcPat->at(offset) == 1) return true;\r
1183   }\r
1184   return false;\r
1185 }\r
1186 \r
1187 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface*, QList<char>* >& pattern, const QList<int> offsets) {\r
1188   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);\r
1189   QListIterator<int> iterOffsets(offsets);\r
1190   while (iterSrc.hasNext()) {\r
1191     iterSrc.next();\r
1192     int offset = iterOffsets.next();\r
1193     QList<char>* srcPat = iterSrc.value();\r
1194     if (offset >= srcPat->size()) return false;\r
1195     if (srcPat->at(offset) == 1) return true;\r
1196   }\r
1197   return false;\r
1198 }\r
1199 \r
1200 bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1201   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1202   while (iterSrc.hasNext()) {\r
1203     iterSrc.next();    \r
1204     QList<char>* srcPat = iterSrc.value();\r
1205     if (offset >= srcPat->size()) return false;\r
1206     if (srcPat->at(offset) != -1) return false;\r
1207   }\r
1208   return true;  \r
1209 }\r
1210 \r
1211 void FunctionalBlock::clearConsumptionPattern() {\r
1212   QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);  \r
1213   while (iterP.hasNext()) {\r
1214     iterP.next();\r
1215     QList<char>* pattern = iterP.value();\r
1216     if (pattern != NULL) delete pattern;\r
1217   }\r
1218   consumptionPattern.clear();\r
1219   lengthCP = -1;      \r
1220 }  \r
1221 \r
1222 void FunctionalBlock::clearProductionPattern() {\r
1223   QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);  \r
1224   while (iterP.hasNext()) {\r
1225     iterP.next();\r
1226     QList<char>* pattern = iterP.value();\r
1227     if (pattern != NULL) delete pattern;\r
1228   }\r
1229   productionPattern.clear();\r
1230   lengthPP = -1;\r
1231 }  \r
1232 \r
1233 void FunctionalBlock::clearInputPattern() {\r
1234   \r
1235   QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
1236   while (iterI.hasNext()) {\r
1237     iterI.next();\r
1238     QList<char>* pattern = iterI.value();\r
1239     if (pattern != NULL) delete pattern;\r
1240   }\r
1241   inputPattern.clear();\r
1242   lengthIP = -1;\r
1243 }\r
1244 \r
1245 void FunctionalBlock::clearOutputPattern() {\r
1246 \r
1247   QMapIterator<AbstractInterface*,QList<char>* > iterO(outputPattern);\r
1248   while (iterO.hasNext()) {\r
1249     iterO.next();\r
1250     ConnectedInterface* connIface = AI_TO_CON(iterO.key());\r
1251     connIface->resetOutputPattern();\r
1252     QList<char>* pattern = iterO.value();\r
1253     if (pattern != NULL) delete pattern;\r
1254   }\r
1255   outputPattern.clear();\r
1256   lengthOP = -1;\r
1257 }\r
1258 \r
1259 void FunctionalBlock::clearAdmittanceDelays() {\r
1260   QMapIterator<AbstractInterface*, QList<int>* > iterA(admittanceDelays);\r
1261   while (iterA.hasNext()) {\r
1262     iterA.next();\r
1263     QList<int>* d = iterA.value();\r
1264     if (d != NULL) delete d;\r
1265   }\r
1266   admittanceDelays.clear();\r
1267 }\r
1268 \r
1269 int FunctionalBlock::createTriggers() {\r
1270   triggers.clear();\r
1271   /* NB: this method returns the number of executions that have been started\r
1272      but not necessary completed.\r
1273   */\r
1274   if (delta <= 0) return 0;  \r
1275   int offset = 0;\r
1276   // search for the first exec.\r
1277   while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;\r
1278   if (offset == lengthIP) return 0;\r
1279   triggers.append(offset);  \r
1280   int nbGroup = 0;\r
1281   for(int i = offset;i<lengthIP;i++) {\r
1282     if (isValidDataGroup(inputPattern,i)) nbGroup++;\r
1283     if (nbGroup == delta+1) {\r
1284       triggers.append(i);\r
1285       nbGroup = 1;\r
1286     }\r
1287   }      \r
1288   return triggers.size();\r
1289 }\r