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

Private GIT Repository
93e83775a979f3eb3bd9af7dc66c306a555ab092
[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 }\r
23 \r
24 \r
25 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {\r
26   /*\r
27   checkedBlocks->append(this);\r
28 \r
29   foreach(BlockParameter* param, params){\r
30     if(param->isUserParameter() && !param->isValueSet()){\r
31       if(!blocksToConfigure->contains(param->getOwner())){\r
32         blocksToConfigure->append(param->getOwner());\r
33       }\r
34     }\r
35   }\r
36   foreach(AbstractInterface *inter, outputs){\r
37     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){\r
38       if(!checkedBlocks->contains(connectedInter->getOwner())){\r
39         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);\r
40       }\r
41     }\r
42   }\r
43   */\r
44 }\r
45 \r
46 bool FunctionalBlock::isFunctionalBlock() {\r
47   return true;\r
48 }\r
49 \r
50 bool FunctionalBlock::isSourceBlock() {\r
51   if (parent == NULL) return true;\r
52   return false;\r
53 }\r
54 \r
55 void FunctionalBlock::populate() {\r
56   int i;\r
57   BlockParameter* p;\r
58   AbstractInterface* inter;\r
59 \r
60   // create parameters from reference block\r
61   QList<BlockParameter*> lstParam = reference->getParameters();\r
62   for(i=0;i<lstParam.size();i++) {\r
63     p = lstParam.at(i)->clone();\r
64     addParameter(p);\r
65   }\r
66 \r
67   // create interfaces from reference block\r
68   QList<AbstractInterface *> lstRef = reference->getInterfaces();\r
69   // store relation between functional and reference\r
70   QHash<AbstractInterface *, AbstractInterface *> hashIface;\r
71   for(i=0;i<lstRef.size();i++) {\r
72     try {\r
73       inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));\r
74     }\r
75     catch(Exception e) {\r
76       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
77       exit(1);\r
78     }\r
79     hashIface.insert(lstRef.at(i),inter);\r
80 \r
81     addInterface(inter);\r
82   }\r
83     \r
84   AbstractInterface* funCtlIface = NULL;\r
85   AbstractInterface* funDataIface = NULL;\r
86   \r
87   for(i=0;i<lstRef.size();i++) {    \r
88     AbstractInterface* refIface = lstRef.at(i);    \r
89     if (refIface->getPurpose() == AbstractInterface::Control) {\r
90       funCtlIface = hashIface.value(refIface);\r
91       funDataIface = hashIface.value(refIface->getAssociatedIface());\r
92       if (! funCtlIface->setAssociatedIface(funDataIface)) {\r
93         cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;\r
94         exit(1);\r
95       }       \r
96     }\r
97   }\r
98 }\r
99 \r
100 \r
101 QString FunctionalBlock::getReferenceXmlFile() {\r
102     return ((ReferenceBlock *)reference)->getXmlFile();\r
103 }\r
104 \r
105 QString FunctionalBlock::getReferenceHashMd5() {\r
106     return ((ReferenceBlock *)reference)->getHashMd5();\r
107 }\r
108 \r
109 void FunctionalBlock::computeOutputPattern(int nbExec) {\r
110   \r
111   /* case 1: the block is a generator for which output pattern\r
112      must be computed for a nbExec following executions\r
113   */\r
114   \r
115   if (nbExec > 0) {\r
116     foreach(AbstractInterface* iface, getControlOutputs()) {\r
117       QList<char> pattern;\r
118       for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();\r
119       iface->setOutputPattern(pattern);\r
120     }    \r
121   }\r
122   else {\r
123     // initialize consumption and production patterns\r
124     initConsumptionPattern();\r
125     initProductionPattern();\r
126     \r
127     // collect the input patterns for each input    \r
128     char** inputPattern = NULL;\r
129     int idIface = 0;\r
130     inputPattern = new char*[nbConsumingPorts];\r
131     int minLen = -1;\r
132     foreach(AbstractInterface* iface, getControlInputs()) {      \r
133       QList<char> in = iface->getConnectedFrom()->getOutputPattern();\r
134       if (minLen == -1) {\r
135         minLen = in.size();\r
136       }\r
137       else {\r
138         if (in.size() < minLen) minLen = in.size();\r
139       }\r
140       inputPattern[idIface] = new char[in.size()];\r
141       int i = 0;\r
142       foreach(char c, in) inputPattern[idIface][i++] = c;\r
143       idIface += 1;      \r
144     }\r
145     // initialize the output pattern    \r
146     char** outputPattern = NULL;\r
147     outputPattern = new char*[nbProducingPorts];\r
148     int lengthOP = 0;\r
149     idIface = 0;\r
150     foreach(AbstractInterface* iface, getControlOutputs()) {\r
151       lengthOP = minLen+iface->getProductionPattern().size();\r
152       outputPattern[idIface] = new char[lengthOP];\r
153       memset(outputPattern[idIface],0,lengthOP);\r
154       idIface += 1;\r
155     }\r
156     \r
157     int clock = 0;\r
158     nbExec = 0;\r
159     // search for the beginning of the first execution.\r
160     while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;\r
161     \r
162     while (clock < minLen) {\r
163       // initialize counters for current execution.\r
164       int p = 0; // index in production pattern\r
165       int o = 0; // clock+o will give the clock cycle of each output group\r
166       int cip = 0; // clock+cip give the clock cycle of an input group\r
167       int ccp = 0; // ccp give a column in the consumptio pattern\r
168       int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
169       int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
170       bool cannotCompleteExec = false;\r
171       for(int m=0;m<productionCounter.size();m++) {\r
172         // search for the first production in PP\r
173         while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {\r
174           p += 1;\r
175           o += 1;\r
176         }\r
177         int gap = 0; // count the number of extra null columns\r
178         // search for PC(m) valid input group in IP\r
179         while (nip < productionCounter.at(m)) {\r
180           if (clock+cip < minLen) {\r
181             if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;\r
182             cip += 1;\r
183             gap += 1;\r
184           }\r
185           else {\r
186             cannotCompleteExec = true;\r
187             break;\r
188           }        \r
189         }\r
190         \r
191         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
192         \r
193         // search for PC(m) valid input group in IP\r
194         while (ncp < productionCounter.at(m)) {\r
195           if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;\r
196           ccp += 1;\r
197           gap -= 1;\r
198         }\r
199         o += gap; // to take into acocunt of extra null columns\r
200         combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);\r
201         p += 1;\r
202         o += 1;\r
203       }\r
204       \r
205       if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
206       \r
207       // current exec. taken into accunt\r
208       nbExec += 1;\r
209       \r
210       // search for the next exec.\r
211       clock += 1;      \r
212       nip = 0;\r
213       while ((clock < minLen) && (nip < delta)) {\r
214         if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;\r
215         if (nip < delta) clock += 1;\r
216       }\r
217     }\r
218     // find the last valid output data group\r
219     while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;\r
220     \r
221     // copy back outputPattern info each interface\r
222     idIface = 0;\r
223     foreach(AbstractInterface* iface, getControlOutputs()) {\r
224       QList<char> pattern;\r
225       for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);\r
226       iface->setOutputPattern(pattern);      \r
227       idIface += 1;\r
228     }\r
229     \r
230     // clear inputPattern and outputPattern\r
231     for(int i=0;i<nbConsumingPorts; i++) {\r
232       delete [] inputPattern[i];\r
233     }\r
234     delete [] inputPattern;\r
235     for(int i=0;i<nbProducingPorts; i++) {\r
236       delete [] outputPattern[i];\r
237     }\r
238     delete [] outputPattern;\r
239   }\r
240 }\r
241 \r
242 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
243   \r
244   for(int i=0;i<nbPorts;i++) {\r
245     if (pattern[i][clock] == 1) return true;\r
246   }\r
247   return false;  \r
248 }\r
249 \r
250 void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {\r
251   \r
252   for (int i=0;i<nbCols;i++) {\r
253     for(int j=0;j<nbPorts;j++) {\r
254       patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];\r
255     }\r
256   }\r
257   \r
258 }\r
259 \r
260 void FunctionalBlock::clearConsumptionPattern() {\r
261   if (consumptionPattern == NULL) return;\r
262   \r
263   for(int i=0;i<nbConsumingPorts; i++) {\r
264     delete [] consumptionPattern[i];\r
265   }\r
266   delete [] consumptionPattern;      \r
267 }\r
268 \r
269 void FunctionalBlock::clearProductionPattern() {\r
270   if (productionPattern == NULL) return;\r
271   for(int i=0;i<nbProducingPorts;i++) {\r
272     delete [] productionPattern[i];\r
273   }\r
274   delete [] productionPattern;\r
275 }\r
276 \r
277 void FunctionalBlock::initConsumptionPattern() {\r
278   if (consumptionPattern != NULL) clearConsumptionPattern();\r
279   \r
280   nbConsumingPorts = getControlInputs().size();  \r
281   int idIface = 0;\r
282   consumptionPattern = new char*[nbConsumingPorts];  \r
283   foreach(AbstractInterface* iface, getControlInputs()) {\r
284     \r
285     QList<char> in = iface->getConsumptionPattern();\r
286     lengthCP = in.size(); // normally, all inputs have the same lenght for CP\r
287     consumptionPattern[idIface] = new char[lengthCP];\r
288     int i = 0;\r
289     foreach(char c, in) consumptionPattern[idIface][i++] = c;\r
290     idIface += 1;    \r
291   }\r
292 }\r
293 \r
294 void FunctionalBlock::initProductionPattern() {\r
295   if (productionPattern != NULL) clearProductionPattern();\r
296   \r
297   nbProducingPorts = getControlOutputs().size();  \r
298   int idIface = 0;\r
299   productionPattern = new char*[nbProducingPorts];  \r
300   foreach(AbstractInterface* iface, getControlOutputs()) {\r
301     \r
302     QList<char> in = iface->getProductionPattern();\r
303     lengthPP = in.size(); // normally, all inputs have the same lenght for PP\r
304     productionPattern[idIface] = new char[lengthPP];\r
305     int i = 0;\r
306     foreach(char c, in) productionPattern[idIface][i++] = c;\r
307     idIface += 1;    \r
308   }\r
309 }\r