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

Private GIT Repository
added generator-cst
[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 \r
9 \r
10 FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) :  AbstractBlock() {\r
11   //if (! _reference->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));\r
12   //if (! _group->isGroupBlock()) throw(Exception(BLOCK_INVALID_TYPE));\r
13   reference = _reference;\r
14   parent = _parent;\r
15   name = reference->getName();\r
16   consumptionPattern = NULL;\r
17   lengthCP = 0;\r
18   nbConsumingPorts = 0;\r
19   productionPattern = NULL;\r
20   lengthPP = 0;\r
21   nbProducingPorts = 0;\r
22   if (reference->getImplementations().isEmpty()) {\r
23     implementation = NULL;\r
24     cout << "block has no implementation" << endl;\r
25   }\r
26   else {\r
27     implementation = reference->getImplementations().at(0);\r
28   }\r
29 }\r
30 \r
31 \r
32 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {\r
33   /*\r
34   checkedBlocks->append(this);\r
35 \r
36   foreach(BlockParameter* param, params){\r
37     if(param->isUserParameter() && !param->isValueSet()){\r
38       if(!blocksToConfigure->contains(param->getOwner())){\r
39         blocksToConfigure->append(param->getOwner());\r
40       }\r
41     }\r
42   }\r
43   foreach(AbstractInterface *inter, outputs){\r
44     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
45       if(!checkedBlocks->contains(connectedInter->getOwner())){\r
46         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
47       }\r
48     }\r
49   }\r
50   */\r
51 }\r
52 \r
53 bool FunctionalBlock::isFunctionalBlock() {\r
54   return true;\r
55 }\r
56 \r
57 bool FunctionalBlock::isSourceBlock() {\r
58   if (parent == NULL) return true;\r
59   return false;\r
60 }\r
61 \r
62 void FunctionalBlock::populate() {\r
63   int i;\r
64   BlockParameter* p;\r
65   AbstractInterface* inter;\r
66 \r
67   // create parameters from reference block\r
68   QList<BlockParameter*> lstParam = reference->getParameters();\r
69   for(i=0;i<lstParam.size();i++) {\r
70     p = lstParam.at(i)->clone();\r
71     addParameter(p);\r
72   }\r
73 \r
74   // create interfaces from reference block\r
75   QList<AbstractInterface *> lstRef = reference->getInterfaces();\r
76   // store relation between functional and reference\r
77   QHash<AbstractInterface *, AbstractInterface *> hashIface;\r
78   for(i=0;i<lstRef.size();i++) {\r
79     try {\r
80       inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));\r
81     }\r
82     catch(Exception e) {\r
83       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
84       exit(1);\r
85     }\r
86     hashIface.insert(lstRef.at(i),inter);\r
87 \r
88     addInterface(inter);\r
89   }\r
90     \r
91   AbstractInterface* funCtlIface = NULL;\r
92   AbstractInterface* funDataIface = NULL;\r
93   \r
94   for(i=0;i<lstRef.size();i++) {    \r
95     AbstractInterface* refIface = lstRef.at(i);    \r
96     if (refIface->getPurpose() == AbstractInterface::Control) {\r
97       funCtlIface = hashIface.value(refIface);\r
98       funDataIface = hashIface.value(refIface->getAssociatedIface());\r
99       if (! funCtlIface->setAssociatedIface(funDataIface)) {\r
100         cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;\r
101         exit(1);\r
102       }       \r
103     }\r
104   }\r
105 }\r
106 \r
107 \r
108 QString FunctionalBlock::getReferenceXmlFile() {\r
109     return ((ReferenceBlock *)reference)->getXmlFile();\r
110 }\r
111 \r
112 QString FunctionalBlock::getReferenceHashMd5() {\r
113     return ((ReferenceBlock *)reference)->getHashMd5();\r
114 }\r
115 \r
116 bool FunctionalBlock::createPatterns() {\r
117   evaluator = new ArithmeticEvaluator();\r
118   bool ok = true;\r
119   ok = ok & createDelta();\r
120   if (ok) ok = ok & createConsumptionPattern();\r
121   if (ok) ok = ok & createProductionCounter();\r
122   if (ok) ok = ok & createProductionPattern();\r
123   delete evaluator;\r
124   return ok;\r
125 }\r
126 \r
127 bool FunctionalBlock::createDelta() {\r
128   QString delta = implementation->getDelta();\r
129   cout << "delta for " << qPrintable(name) << " = " << qPrintable(delta) << endl;\r
130   \r
131   // look for parameter names\r
132   QHash<QString,double> vars;\r
133   QRegularExpression re("[$][a-zA-Z0-9_]+");\r
134   QRegularExpressionMatchIterator matcher = re.globalMatch(delta);\r
135   while(matcher.hasNext()) {\r
136     QRegularExpressionMatch m = matcher.next();\r
137     QString var = m.captured(0);\r
138     cout << qPrintable(var) << endl;\r
139     vars.insert(var,0.0);    \r
140   }\r
141   QHashIterator<QString,double> iterV(vars);\r
142   while (iterV.hasNext()) {\r
143     iterV.next();\r
144     QString var = iterV.key();\r
145     QString paramName = var.remove(0,1);\r
146     BlockParameter* param = reference->getParameterFromName(paramName);\r
147     cout << "param = " << qPrintable(param->getStringValue()) << endl;\r
148     if (param == NULL) {\r
149       cerr << "found an unknown parameter in delta"<< endl;\r
150       return false;\r
151     }\r
152     bool ok;\r
153     int val = param->getIntValue(&ok);\r
154     vars.insert(var,(double)val);\r
155   }\r
156   cout << "set expr " << endl;\r
157   evaluator->setExpression(delta);\r
158   cout << "set vars " << endl;\r
159   evaluator->setVariablesValue(vars);\r
160   double result = evaluator->evaluate();\r
161   cout << "delta = " << result << endl;\r
162    \r
163   return true;\r
164 }\r
165 \r
166 bool FunctionalBlock::createConsumptionPattern() {\r
167   return true;\r
168 }\r
169 \r
170 bool FunctionalBlock::createProductionPattern() {\r
171   return true;\r
172 }\r
173 \r
174 bool FunctionalBlock::createProductionCounter() {\r
175   return true;\r
176 }\r
177 \r
178 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
179   \r
180   /* case 1: the block is a generator for which output pattern\r
181      must be computed for a nbExec following executions\r
182   */\r
183   \r
184   if (nbExec > 0) {\r
185     foreach(AbstractInterface* iface, getControlOutputs()) {\r
186       QList<char> pattern;\r
187       for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();\r
188       iface->setOutputPattern(pattern);\r
189     }    \r
190   }\r
191   else {\r
192     // initialize consumption and production patterns\r
193     initConsumptionPattern();\r
194     initProductionPattern();\r
195     \r
196     // collect the input patterns for each input    \r
197     char** inputPattern = NULL;\r
198     int idIface = 0;\r
199     inputPattern = new char*[nbConsumingPorts];\r
200     int minLen = -1;\r
201     foreach(AbstractInterface* iface, getControlInputs()) {      \r
202       QList<char> in = iface->getConnectedFrom()->getOutputPattern();\r
203       if (minLen == -1) {\r
204         minLen = in.size();\r
205       }\r
206       else {\r
207         if (in.size() < minLen) minLen = in.size();\r
208       }\r
209       if (in.size() > 0) {\r
210         inputPattern[idIface] = new char[in.size()];\r
211         int i = 0;\r
212         foreach(char c, in) inputPattern[idIface][i++] = c;\r
213       }\r
214       else {\r
215         inputPattern[idIface] = NULL;\r
216       }\r
217       idIface += 1;      \r
218     }\r
219     // if some patterns are not available, ens now, returning false\r
220     if (minLen == 0) {\r
221       for(int i=0;i<nbConsumingPorts; i++) {\r
222         if (inputPattern[i] != NULL) delete [] inputPattern[i];\r
223       }\r
224       delete [] inputPattern;\r
225       return false;\r
226     }\r
227     // initialize the output pattern    \r
228     char** outputPattern = NULL;\r
229     outputPattern = new char*[nbProducingPorts];\r
230     int lengthOP = 0;\r
231     idIface = 0;\r
232     foreach(AbstractInterface* iface, getControlOutputs()) {\r
233       lengthOP = minLen+iface->getProductionPattern().size();\r
234       outputPattern[idIface] = new char[lengthOP];\r
235       memset(outputPattern[idIface],0,lengthOP);\r
236       idIface += 1;\r
237     }\r
238     \r
239     int clock = 0;\r
240     nbExec = 0;\r
241     // search for the beginning of the first execution.\r
242     while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;\r
243     \r
244     while (clock < minLen) {\r
245       // initialize counters for current execution.\r
246       int p = 0; // index in production pattern\r
247       int o = 0; // clock+o will give the clock cycle of each output group\r
248       int cip = 0; // clock+cip give the clock cycle of an input group\r
249       int ccp = 0; // ccp give a column in the consumptio pattern\r
250       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
251       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
252       bool cannotCompleteExec = false;\r
253       for(int m=0;m<productionCounter.size();m++) {\r
254         // search for the first production in PP\r
255         while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {\r
256           p += 1;\r
257           o += 1;\r
258         }\r
259         int gap = 0; // count the number of extra null columns\r
260         // search for PC(m) valid input group in IP\r
261         while (nip < productionCounter.at(m)) {\r
262           if (clock+cip < minLen) {\r
263             if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;\r
264             cip += 1;\r
265             gap += 1;\r
266           }\r
267           else {\r
268             cannotCompleteExec = true;\r
269             break;\r
270           }        \r
271         }\r
272         \r
273         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
274         \r
275         // search for PC(m) valid input group in IP\r
276         while (ncp < productionCounter.at(m)) {\r
277           if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;\r
278           ccp += 1;\r
279           gap -= 1;\r
280         }\r
281         o += gap; // to take into acocunt of extra null columns\r
282         combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);\r
283         p += 1;\r
284         o += 1;\r
285       }\r
286       \r
287       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
288       \r
289       // current exec. taken into accunt\r
290       nbExec += 1;\r
291       \r
292       // search for the next exec.\r
293       clock += 1;      \r
294       nip = 0;\r
295       while ((clock < minLen) && (nip < delta)) {\r
296         if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;\r
297         if (nip < delta) clock += 1;\r
298       }\r
299     }\r
300     // find the last valid output data group\r
301     while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;\r
302     \r
303     // copy back outputPattern info each interface\r
304     idIface = 0;\r
305     foreach(AbstractInterface* iface, getControlOutputs()) {\r
306       QList<char> pattern;\r
307       for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);\r
308       iface->setOutputPattern(pattern);      \r
309       idIface += 1;\r
310     }\r
311     \r
312     // clear inputPattern and outputPattern\r
313     for(int i=0;i<nbConsumingPorts; i++) {\r
314       delete [] inputPattern[i];\r
315     }\r
316     delete [] inputPattern;\r
317     for(int i=0;i<nbProducingPorts; i++) {\r
318       delete [] outputPattern[i];\r
319     }\r
320     delete [] outputPattern;\r
321   }\r
322   return true;\r
323 }\r
324 \r
325 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
326   \r
327   for(int i=0;i<nbPorts;i++) {\r
328     if (pattern[i][clock] == 1) return true;\r
329   }\r
330   return false;  \r
331 }\r
332 \r
333 void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {\r
334   \r
335   for (int i=0;i<nbCols;i++) {\r
336     for(int j=0;j<nbPorts;j++) {\r
337       patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];\r
338     }\r
339   }\r
340   \r
341 }\r
342 \r
343 void FunctionalBlock::clearConsumptionPattern() {\r
344   if (consumptionPattern == NULL) return;\r
345   \r
346   for(int i=0;i<nbConsumingPorts; i++) {\r
347     delete [] consumptionPattern[i];\r
348   }\r
349   delete [] consumptionPattern;      \r
350 }\r
351 \r
352 void FunctionalBlock::clearProductionPattern() {\r
353   if (productionPattern == NULL) return;\r
354   for(int i=0;i<nbProducingPorts;i++) {\r
355     delete [] productionPattern[i];\r
356   }\r
357   delete [] productionPattern;\r
358 }\r
359 \r
360 void FunctionalBlock::initConsumptionPattern() {\r
361   if (consumptionPattern != NULL) clearConsumptionPattern();\r
362   \r
363   nbConsumingPorts = getControlInputs().size();  \r
364   int idIface = 0;\r
365   consumptionPattern = new char*[nbConsumingPorts];  \r
366   foreach(AbstractInterface* iface, getControlInputs()) {\r
367     \r
368     QList<char> in = iface->getConsumptionPattern();\r
369     lengthCP = in.size(); // normally, all inputs have the same lenght for CP\r
370     consumptionPattern[idIface] = new char[lengthCP];\r
371     int i = 0;\r
372     foreach(char c, in) consumptionPattern[idIface][i++] = c;\r
373     idIface += 1;    \r
374   }\r
375 }\r
376 \r
377 void FunctionalBlock::initProductionPattern() {\r
378   if (productionPattern != NULL) clearProductionPattern();\r
379   \r
380   nbProducingPorts = getControlOutputs().size();  \r
381   int idIface = 0;\r
382   productionPattern = new char*[nbProducingPorts];  \r
383   foreach(AbstractInterface* iface, getControlOutputs()) {\r
384     \r
385     QList<char> in = iface->getProductionPattern();\r
386     lengthPP = in.size(); // normally, all inputs have the same lenght for PP\r
387     productionPattern[idIface] = new char[lengthPP];\r
388     int i = 0;\r
389     foreach(char c, in) productionPattern[idIface][i++] = c;\r
390     idIface += 1;    \r
391   }\r
392 }\r