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

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