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

Private GIT Repository
91f4e03798c1403f63cd0128258df45630c01f7a
[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 \r
653     ConnectedInterface* assoIface = AI_TO_CON(connIface->getAssociatedIface());\r
654     AbstractInputModifier* modifier = assoIface->getInputModifier();\r
655     // check if the input is modified\r
656     if (modifier != NULL) {\r
657 \r
658       out = modifier->getModifiedInput(out);\r
659     }\r
660 \r
661     if (out->size() == 0) {\r
662       clearInputPattern();\r
663       throw(Exception(NO_IFACE_IP,this));\r
664     }\r
665     if (lengthIP == -1) {\r
666       lengthIP = out->size();\r
667     }\r
668     else {\r
669       if (out->size() < lengthIP) lengthIP = out->size();\r
670     }\r
671     \r
672     QList<char>* in = new QList<char>(*out);\r
673     foreach(char c, *in) {\r
674       cout << (int)c;\r
675     }\r
676     cout << endl;    \r
677     inputPattern.insert(connIface,in);    \r
678   }\r
679   // search the last valid group in IP,\r
680   while(! isValidDataGroup(inputPattern,lengthIP-1)) {\r
681     //removeDataGroup(inputPattern,lengthIP-1);\r
682     lengthIP -= 1;\r
683   }\r
684 }\r
685 \r
686 void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) {\r
687   static QString fctName = "FunctionalBlock::createAdmittance()";\r
688 #ifdef DEBUG_FCTNAME\r
689   cout << "call to " << qPrintable(fctName) << endl;\r
690 #endif  \r
691   // firstly, copy CP in AP\r
692   QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);\r
693   while (iterC.hasNext()) {\r
694     iterC.next();\r
695     QList<char>* pattern = new QList<char>(*(iterC.value()));\r
696     admittance.insert(iterC.key(), pattern);    \r
697   }\r
698   lengthAP = lengthCP;\r
699   int clock = 0;  \r
700   cout << "trigger 1 at c.c. 0" << endl;\r
701   for(int i=1;i<nbExec;i++) {\r
702     // searching for the clock cycle for which a new exec starts\r
703     int nbGroup = 0;\r
704     while ((clock < lengthAP) && (nbGroup < delta)) {\r
705       if (isValidDataGroup(admittance,clock)) nbGroup+=1;\r
706       clock += 1;\r
707     }\r
708     while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;\r
709     cout << "trigger " << (i+1) << " at c.c. " << clock << endl;\r
710     int sc = clock;\r
711     // combine CP with AP at sc\r
712     for(int j=0;j<lengthCP;j++) {\r
713       // first case : column of CP must be placed beyond AP's end.\r
714       if (sc == lengthAP) {\r
715         cout << i << "," << j << " append in AP at " << sc << endl;\r
716         appendToPattern(consumptionPattern,j,admittance,1);\r
717         lengthAP += 1;\r
718         sc += 1;               \r
719       }\r
720       // second case : CP and AP can be combined directly (i.e. no X | 1 to do)\r
721       else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
722         cout << i << "," << j << " combine at " << sc << endl;\r
723         combinePatterns(consumptionPattern,j,admittance,sc);\r
724         sc += 1;\r
725       }\r
726       // third case : CP has an X column\r
727       else if (isOnlyXDataGroup(consumptionPattern,j)) {\r
728         cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;\r
729         shiftRightPattern(admittance,sc);\r
730         lengthAP += 1;\r
731         if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
732           cerr << "Abnormal case when combining AP and CP" << endl;\r
733         }\r
734         combinePatterns(consumptionPattern,j,admittance,sc);        \r
735         sc += 1;\r
736       }\r
737       // fourth case : AP has an X column\r
738       else if (isOnlyXDataGroup(admittance,sc)) {\r
739         cout << i << "," << j << " jump c.c. for CP at " << sc << endl;        \r
740         sc += 1;\r
741         j -= 1;\r
742       }\r
743       else {\r
744         throw(INVALID_DELTA_CP);        \r
745       }\r
746     }\r
747   }\r
748   // turn all X into 0\r
749   QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);\r
750   while (iterA.hasNext()) {\r
751     iterA.next();\r
752     QList<char>* pattern = iterA.value();\r
753     for(int i=0;i<pattern->size();i++) {\r
754       if (pattern->at(i) == -1) pattern->replace(i,0);\r
755       cout << (int)(pattern->at(i));\r
756     }\r
757     cout << endl;\r
758   }  \r
759 }\r
760 \r
761 void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) {\r
762   static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
763 #ifdef DEBUG_FCTNAME\r
764   cout << "call to " << qPrintable(fctName) << endl;\r
765 #endif\r
766     \r
767   // firstly, create input pattern\r
768   try {\r
769     createInputPattern();\r
770   }\r
771   catch(Exception e) {\r
772     throw(e);\r
773   }\r
774   int nbExec = createTriggers();\r
775   cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;\r
776   \r
777   try {\r
778     createAdmittance(nbExec);\r
779   }\r
780   catch(Exception e) {\r
781     cout << "cannot create admittance" << endl;\r
782     throw(e);\r
783   }\r
784   \r
785   int clock = 0; // index in IP  \r
786   int i = 0; // index in AP  \r
787   while ((clock < lengthIP) && (i < lengthAP)) {\r
788      \r
789     // if AP is a valid group, search for the next valid group in IP\r
790     if (isValidDataGroup(admittance,i)) {\r
791       while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
792       if (clock == lengthIP) {\r
793         cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;\r
794         throw(Exception(IP_END_NULLCOL,this));\r
795       }\r
796     }    \r
797     /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or\r
798        are both null columns\r
799     */\r
800     if (! samePatterns(inputPattern,clock,admittance,i)) {\r
801       cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;\r
802       throw(Exception(IP_AP_NOTCOMPAT,this)); // IP and AP not compatible\r
803     }\r
804     clock++;\r
805     i++;\r
806   }\r
807   if (clock < lengthIP) {\r
808     throw(Exception(AP_TOO_SHORT,this));\r
809     cerr << "Abnormal case: AP is to short" << endl;   \r
810   }  \r
811 }\r
812 \r
813 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {\r
814   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
815 #ifdef DEBUG_FCTNAME\r
816   cout << "call to " << qPrintable(fctName) << endl;\r
817 #endif\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   \r
824   if (nbExec > 0) {\r
825     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
826     foreach(AbstractInterface* iface, getControlOutputs()) {\r
827       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
828       // create output pattern\r
829       QList<char>* pp = productionPattern.value(connIface);\r
830       QList<char>* pattern = new QList<char>(*pp);\r
831       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
832       // assign pattern to interface\r
833       connIface->setOutputPattern(pattern);\r
834       // store it in QMap\r
835       outputPattern.insert(connIface,pattern);      \r
836     }\r
837   }\r
838   else {\r
839     cout << "computing output pattern of " << qPrintable(name) << endl;\r
840     \r
841     // in case of inputPattern not created, do it\r
842     if (lengthIP <= 0) {\r
843 \r
844       cout << "Strange case: input pattern is not created while it is time to compute output pattern !" << endl;\r
845       // collect the input patterns for each input    \r
846       try {\r
847         createInputPattern();\r
848       }\r
849       catch(Exception e) {\r
850         throw(e);\r
851       }\r
852       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
853     }\r
854     \r
855     // initialize the output pattern    \r
856     lengthOP = 0;\r
857     foreach(AbstractInterface* iface, getControlOutputs()) {\r
858       FunctionalInterface* connIface = AI_TO_FUN(iface);      \r
859       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
860       QList<char>* pattern = new QList<char>();\r
861       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
862       connIface->setOutputPattern(pattern);\r
863       outputPattern.insert(connIface,pattern);\r
864     }\r
865     cout << "output pattern array initialized" << endl;\r
866     \r
867     int clock = 0;\r
868     nbExec = 0;\r
869     // search for the beginning of the first execution.\r
870     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
871     cout << "found 1st exec clock: " << clock << endl;\r
872     \r
873     while (clock < lengthIP) {\r
874       // initialize counters for current execution.\r
875       int p = 0; // index in production pattern\r
876       int o = 0; // clock+o will give the clock cycle of each output group\r
877       int cip = 0; // clock+cip give the clock cycle of an input group\r
878       int ccp = 0; // ccp give a column in the consumptio pattern\r
879       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
880       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
881       bool cannotCompleteExec = false;\r
882       for(int m=0;m<productionCounter.size();m++) {\r
883         // search for the first production in PP\r
884         while (!isValidDataGroup(productionPattern,p)) {\r
885           p += 1;\r
886           o += 1;\r
887         }\r
888         int gap = 0; // count the number of extra null columns\r
889         // search for PC(m) valid input group in IP\r
890         while (nip < productionCounter.at(m)) {\r
891           if (clock+cip < lengthIP) {\r
892             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
893             cip += 1;\r
894             gap += 1;\r
895           }\r
896           else {\r
897             cannotCompleteExec = true;\r
898             break;\r
899           }        \r
900         }        \r
901         \r
902         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
903         \r
904         // search for PC(m) valid input group in IP\r
905         while (ncp < productionCounter.at(m)) {\r
906           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
907           ccp += 1;\r
908           gap -= 1;\r
909         }\r
910         o += gap; // to take into acocunt of extra null columns\r
911         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
912         p += 1;\r
913         o += 1;\r
914       }\r
915       \r
916       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
917       \r
918       // current exec. taken into accunt\r
919       nbExec += 1;\r
920       \r
921       // search for the next exec.\r
922       clock += 1;      \r
923       nip = 0;\r
924       while ((clock < lengthIP) && (nip < delta)) {\r
925         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
926         if (nip < delta) clock += 1;\r
927       }\r
928       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
929     }\r
930     // find the last valid output data group\r
931     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
932       removeDataGroup(outputPattern,lengthOP-1);\r
933       lengthOP -= 1;\r
934     }\r
935 \r
936     // clear input pattern\r
937     clearInputPattern();\r
938   }  \r
939 }\r
940 \r
941 /*\r
942 \r
943 void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {\r
944   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
945 #ifdef DEBUG_FCTNAME\r
946   cout << "call to " << qPrintable(fctName) << endl;\r
947 #endif\r
948 \r
949   // case 1: the block is a generator for which output pattern\r
950   //   must be computed for a nbExec following executions\r
951 \r
952   if (nbExec > 0) {\r
953     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
954     foreach(AbstractInterface* iface, getControlOutputs()) {\r
955       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
956       // create output pattern\r
957       QList<char>* pp = productionPattern.value(connIface);\r
958       QList<char>* pattern = new QList<char>(*pp);\r
959       for(int i=1;i<nbExec;i++) pattern->append(*pp);\r
960       // assign pattern to interface\r
961       connIface->setOutputPattern(pattern);\r
962       // store it in QMap\r
963       outputPattern.insert(connIface,pattern);\r
964     }\r
965   }\r
966   else {\r
967     cout << "computing output pattern of " << qPrintable(name) << endl;\r
968 \r
969     // in case of inputPattern not created, do it\r
970     if (lengthIP <= 0) {\r
971       // collect the input patterns for each input\r
972       try {\r
973         createInputPattern();\r
974       }\r
975       catch(Exception e) {\r
976         throw(e);\r
977       }\r
978       cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
979     }\r
980 \r
981     // initialize the output pattern\r
982     lengthOP = 0;\r
983     foreach(AbstractInterface* iface, getControlOutputs()) {\r
984       FunctionalInterface* connIface = AI_TO_FUN(iface);\r
985       lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
986       QList<char>* pattern = new QList<char>();\r
987       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
988       connIface->setOutputPattern(pattern);\r
989       outputPattern.insert(connIface,pattern);\r
990     }\r
991     cout << "output pattern array initialized" << endl;\r
992 \r
993     int clock = 0;\r
994     nbExec = 0;\r
995     // search for the beginning of the first execution.\r
996     while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
997     cout << "found 1st exec clock: " << clock << endl;\r
998 \r
999     while (clock < lengthIP) {\r
1000       // initialize counters for current execution.\r
1001       int p = 0; // index in production pattern\r
1002       int o = 0; // clock+o will give the clock cycle of each output group\r
1003       int cip = 0; // clock+cip give the clock cycle of an input group\r
1004       int ccp = 0; // ccp give a column in the consumptio pattern\r
1005       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
1006       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
1007       bool cannotCompleteExec = false;\r
1008       for(int m=0;m<productionCounter.size();m++) {\r
1009         // search for the first production in PP\r
1010         while (!isValidDataGroup(productionPattern,p)) {\r
1011           p += 1;\r
1012           o += 1;\r
1013         }\r
1014         int gap = 0; // count the number of extra null columns\r
1015         // search for PC(m) valid input group in IP\r
1016         while (nip < productionCounter.at(m)) {\r
1017           if (clock+cip < lengthIP) {\r
1018             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
1019             cip += 1;\r
1020             gap += 1;\r
1021           }\r
1022           else {\r
1023             cannotCompleteExec = true;\r
1024             break;\r
1025           }\r
1026         }\r
1027 \r
1028         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
1029 \r
1030         // search for PC(m) valid input group in IP\r
1031         while (ncp < productionCounter.at(m)) {\r
1032           if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;\r
1033           ccp += 1;\r
1034           gap -= 1;\r
1035         }\r
1036         o += gap; // to take into acocunt of extra null columns\r
1037         combinePatterns(productionPattern,p,outputPattern,clock+o);\r
1038         p += 1;\r
1039         o += 1;\r
1040       }\r
1041 \r
1042       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
1043 \r
1044       // current exec. taken into accunt\r
1045       nbExec += 1;\r
1046 \r
1047       // search for the next exec.\r
1048       clock += 1;\r
1049       nip = 0;\r
1050       while ((clock < lengthIP) && (nip < delta)) {\r
1051         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
1052         if (nip < delta) clock += 1;\r
1053       }\r
1054       cout << "found exec " << nbExec << " at clock: " << clock << endl;\r
1055     }\r
1056     // find the last valid output data group\r
1057     while(! isValidDataGroup(outputPattern,lengthOP-1)) {\r
1058       removeDataGroup(outputPattern,lengthOP-1);\r
1059       lengthOP -= 1;\r
1060     }\r
1061 \r
1062     // clear input pattern\r
1063     clearInputPattern();\r
1064   }\r
1065 }\r
1066 */\r
1067 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
1068   \r
1069   if (patternSrc.size() != patternDest.size()) return false;\r
1070   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1071   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1072   while (iterSrc.hasNext()) {\r
1073     iterSrc.next();\r
1074     iterDest.next();    \r
1075     QList<char>* srcPat = iterSrc.value();\r
1076     QList<char>* destPat = iterDest.value();\r
1077     if (srcCol >= srcPat->size()) return false;\r
1078     if (destCol >= destPat->size()) return false;\r
1079     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;    \r
1080   }\r
1081   return true;\r
1082 }\r
1083 \r
1084 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, const QList<int> &srcCols, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {\r
1085   if (patternSrc.size() != srcCols.size()) return false;\r
1086   if (patternSrc.size() != patternDest.size()) return false;\r
1087 \r
1088   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1089   QListIterator<int> iterSrcCol(srcCols);\r
1090   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1091   while (iterSrc.hasNext()) {\r
1092     iterSrc.next();\r
1093     int srcCol = iterSrcCol.next();\r
1094     iterDest.next();\r
1095     QList<char>* srcPat = iterSrc.value();\r
1096     QList<char>* destPat = iterDest.value();\r
1097     if (srcCol >= srcPat->size()) return false;\r
1098     if (destCol >= destPat->size()) return false;\r
1099     if (srcPat->at(srcCol) != destPat->at(destCol)) return false;\r
1100   }\r
1101   return true;\r
1102 }\r
1103 \r
1104 bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
1105   if (patternSrc.size() != patternDest.size()) return false;\r
1106   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1107   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1108   while (iterSrc.hasNext()) {\r
1109     iterSrc.next();\r
1110     iterDest.next();    \r
1111     QList<char>* srcPat = iterSrc.value();\r
1112     QList<char>* destPat = iterDest.value();\r
1113     if (srcCol >= srcPat->size()) return false;\r
1114     if (destCol >= destPat->size()) return false;\r
1115     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;\r
1116     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;\r
1117   }\r
1118   return true;\r
1119 }\r
1120 \r
1121 void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {\r
1122   if (patternSrc.size() != patternDest.size()) return;\r
1123   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1124   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1125   while (iterSrc.hasNext()) {\r
1126     iterSrc.next();\r
1127     iterDest.next();    \r
1128     QList<char>* srcPat = iterSrc.value();\r
1129     QList<char>* destPat = iterDest.value();\r
1130     if (srcCol >= srcPat->size()) return;\r
1131     if (destCol >= destPat->size()) return;\r
1132     if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;\r
1133     if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;    \r
1134     destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));\r
1135   }  \r
1136 }\r
1137 \r
1138 void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {\r
1139   if (patternSrc.size() != patternDest.size()) return;\r
1140   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);\r
1141   QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);\r
1142   while (iterSrc.hasNext()) {\r
1143     iterSrc.next();\r
1144     iterDest.next();    \r
1145     QList<char>* srcPat = iterSrc.value();\r
1146     QList<char>* destPat = iterDest.value();    \r
1147     int i=0;\r
1148     while ((srcCol+i < srcPat->size()) && (i<nbCols)) {\r
1149       destPat->append(srcPat->at(srcCol+i));\r
1150       i++;\r
1151     }\r
1152   }  \r
1153 }\r
1154 \r
1155 void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1156   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1157   while (iterSrc.hasNext()) {\r
1158     iterSrc.next();    \r
1159     QList<char>* srcPat = iterSrc.value();\r
1160     if (offset < srcPat->size()) {\r
1161       srcPat->removeAt(offset);\r
1162     }\r
1163   }\r
1164 }\r
1165 \r
1166 void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1167   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1168   while (iterSrc.hasNext()) {\r
1169     iterSrc.next();    \r
1170     QList<char>* srcPat = iterSrc.value();\r
1171     if (offset < srcPat->size()) {\r
1172       srcPat->insert(offset,0);\r
1173     }\r
1174   }\r
1175 }\r
1176 \r
1177 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1178   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1179   while (iterSrc.hasNext()) {\r
1180     iterSrc.next();    \r
1181     QList<char>* srcPat = iterSrc.value();\r
1182     if (offset >= srcPat->size()) return false;\r
1183     if (srcPat->at(offset) == 1) return true;\r
1184   }\r
1185   return false;\r
1186 }\r
1187 \r
1188 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface*, QList<char>* >& pattern, const QList<int> offsets) {\r
1189   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);\r
1190   QListIterator<int> iterOffsets(offsets);\r
1191   while (iterSrc.hasNext()) {\r
1192     iterSrc.next();\r
1193     int offset = iterOffsets.next();\r
1194     QList<char>* srcPat = iterSrc.value();\r
1195     if (offset >= srcPat->size()) return false;\r
1196     if (srcPat->at(offset) == 1) return true;\r
1197   }\r
1198   return false;\r
1199 }\r
1200 \r
1201 bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
1202   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
1203   while (iterSrc.hasNext()) {\r
1204     iterSrc.next();    \r
1205     QList<char>* srcPat = iterSrc.value();\r
1206     if (offset >= srcPat->size()) return false;\r
1207     if (srcPat->at(offset) != -1) return false;\r
1208   }\r
1209   return true;  \r
1210 }\r
1211 \r
1212 void FunctionalBlock::clearConsumptionPattern() {\r
1213   QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);  \r
1214   while (iterP.hasNext()) {\r
1215     iterP.next();\r
1216     QList<char>* pattern = iterP.value();\r
1217     if (pattern != NULL) delete pattern;\r
1218   }\r
1219   consumptionPattern.clear();\r
1220   lengthCP = -1;      \r
1221 }  \r
1222 \r
1223 void FunctionalBlock::clearProductionPattern() {\r
1224   QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);  \r
1225   while (iterP.hasNext()) {\r
1226     iterP.next();\r
1227     QList<char>* pattern = iterP.value();\r
1228     if (pattern != NULL) delete pattern;\r
1229   }\r
1230   productionPattern.clear();\r
1231   lengthPP = -1;\r
1232 }  \r
1233 \r
1234 void FunctionalBlock::clearInputPattern() {\r
1235   \r
1236   QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
1237   while (iterI.hasNext()) {\r
1238     iterI.next();\r
1239     QList<char>* pattern = iterI.value();\r
1240     if (pattern != NULL) delete pattern;\r
1241   }\r
1242   inputPattern.clear();\r
1243   lengthIP = -1;\r
1244 }\r
1245 \r
1246 void FunctionalBlock::clearAdmittanceDelays() {\r
1247   QMapIterator<AbstractInterface*, QList<int>* > iterA(admittanceDelays);\r
1248   while (iterA.hasNext()) {\r
1249     iterA.next();\r
1250     QList<int>* d = iterA.value();\r
1251     if (d != NULL) delete d;\r
1252   }\r
1253   admittanceDelays.clear();\r
1254 }\r
1255 \r
1256 int FunctionalBlock::createTriggers() {\r
1257   triggers.clear();\r
1258   /* NB: this method returns the number of executions that have been started\r
1259      but not necessary completed.\r
1260   */\r
1261   if (delta <= 0) return 0;  \r
1262   int offset = 0;\r
1263   // search for the first exec.\r
1264   while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;\r
1265   if (offset == lengthIP) return 0;\r
1266   triggers.append(offset);  \r
1267   int nbGroup = 0;\r
1268   for(int i = offset;i<lengthIP;i++) {\r
1269     if (isValidDataGroup(inputPattern,i)) nbGroup++;\r
1270     if (nbGroup == delta+1) {\r
1271       triggers.append(i);\r
1272       nbGroup = 1;\r
1273     }\r
1274   }      \r
1275   return triggers.size();\r
1276 }\r