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

Private GIT Repository
b7510217a5cce885b85b5c522d381fa26ab50e39
[blast.git] / BlockImplementation.cpp
1 #include "BlockImplementation.h"\r
2 \r
3 #include "FunctionalBlock.h"\r
4 #include "ReferenceBlock.h"\r
5 #include "ReferenceInterface.h"\r
6 #include "FunctionalInterface.h"\r
7 #include "BlockParameter.h"\r
8 #include <QHashIterator>\r
9 \r
10 \r
11 BlockImplementation::BlockImplementation(const QString& _xmlFile) {\r
12   xmlFile = _xmlFile;\r
13   productionCounter = "";\r
14   delta = "";\r
15 \r
16   evaluator = new ArithmeticEvaluator;\r
17   evaluator->setVariableMarkers("@$");\r
18 }\r
19 \r
20 BlockImplementation::BlockImplementation(const QString& _xmlFile, const QString &_referenceXml, const QString &_referenceMd5) {\r
21   xmlFile = _xmlFile;  \r
22   productionCounter = "";\r
23   delta = "";\r
24   referenceXml = _referenceXml;\r
25   referenceMd5 = _referenceMd5;\r
26 }\r
27 \r
28 void BlockImplementation::loadPatterns(QDomElement& root) throw(Exception) {\r
29     \r
30   QDomNodeList patternNode = root.elementsByTagName("patterns");\r
31   \r
32   if (patternNode.isEmpty()) {\r
33     cout << "impl has no patterns" << endl;\r
34     return;\r
35   }\r
36   \r
37   QDomElement patternElt = patternNode.at(0).toElement();\r
38   \r
39   QDomElement eltDelta  = patternElt.firstChildElement("delta");\r
40   delta = eltDelta.attribute("value","none");\r
41   \r
42   QDomElement eltCons  = eltDelta.nextSiblingElement("consumption");\r
43   \r
44   QDomNodeList listNodeInput = eltCons.elementsByTagName("input");\r
45   for(int i=0; i<listNodeInput.size(); i++) {\r
46     QDomNode node = listNodeInput.at(i);    \r
47     QDomElement elt = node.toElement();    \r
48     QString nameStr = elt.attribute("name","none");\r
49     if (nameStr == "none") throw(Exception(IMPLFILE_CORRUPTED));\r
50     QString patternStr = elt.attribute("pattern","none");    \r
51     consumptionPattern.insert(nameStr,patternStr);\r
52   }\r
53   \r
54   QDomElement eltProd  = eltCons.nextSiblingElement("production");\r
55   \r
56   productionCounter = eltProd.attribute("counter","none");\r
57   QDomNodeList listNodeOutput = eltProd.elementsByTagName("output");\r
58   for(int i=0; i<listNodeOutput.size(); i++) {\r
59     QDomNode node = listNodeOutput.at(i);    \r
60     QDomElement elt = node.toElement();        \r
61     QString nameStr = elt.attribute("name","none");\r
62     if (nameStr == "none") throw(Exception(IMPLFILE_CORRUPTED));\r
63     QString patternStr = elt.attribute("pattern","none");    \r
64     productionPattern.insert(nameStr,patternStr);    \r
65   }\r
66   cout << "patterns summary:" << endl;\r
67   QHashIterator<QString,QString> iterP(productionPattern);\r
68   while (iterP.hasNext()) {\r
69     iterP.next();\r
70     cout << qPrintable(iterP.key()) << " -> " << qPrintable(iterP.value()) << endl;\r
71   }\r
72   cout << "impls patterns read correctly" << endl;\r
73 }\r
74 \r
75 bool BlockImplementation::checkPatterns() {\r
76   if (reference == NULL) return false;\r
77   \r
78   AbstractInterface* iface;  \r
79   QHashIterator<QString,QString> iterI(consumptionPattern);\r
80   while (iterI.hasNext()) {\r
81     iterI.next();\r
82     iface = reference->getIfaceFromName(iterI.key());\r
83     if (iface == NULL) return false;\r
84   }\r
85   QHashIterator<QString,QString> iterO(productionPattern);\r
86   while (iterO.hasNext()) {\r
87     iterO.next();\r
88     iface = reference->getIfaceFromName(iterO.key());\r
89     if (iface == NULL) return false;\r
90   }  \r
91   return true;  \r
92 }\r
93 \r
94 void BlockImplementation::generateVHDL(FunctionalBlock* _block, const QString &path) throw(Exception) {\r
95 \r
96   block = _block;\r
97 \r
98   QFile implFile(xmlFile);\r
99 \r
100   // reading in into QDomDocument\r
101   QDomDocument document("implFile");\r
102 \r
103   if (!implFile.open(QIODevice::ReadOnly)) {\r
104     throw(Exception(IMPLFILE_NOACCESS));\r
105   }\r
106   if (!document.setContent(&implFile)) {\r
107     implFile.close();\r
108     throw(Exception(IMPLFILE_NOACCESS));\r
109   }\r
110   implFile.close();\r
111 \r
112   bool genController = false;\r
113   QString coreFile = "";\r
114   QString controllerFile = "";\r
115 \r
116   if (reference->isWBConfigurable()) {\r
117     genController = true;\r
118     controllerFile = path;\r
119     controllerFile.append(block->getName());\r
120     controllerFile.append("_ctrl.vhd");    \r
121   }\r
122   else {\r
123     controllerFile = "nofile.vhd";    \r
124   }\r
125   coreFile = path;\r
126   coreFile.append(block->getName());\r
127   coreFile.append(".vhd");\r
128 \r
129   QFile vhdlCore(coreFile);\r
130   QFile vhdlController(controllerFile);\r
131 \r
132   if (!vhdlCore.open(QIODevice::WriteOnly)) {\r
133     throw(Exception(VHDLFILE_NOACCESS));\r
134   }\r
135 \r
136   if (genController) {\r
137     if (!vhdlController.open(QIODevice::WriteOnly)) {\r
138       throw(Exception(VHDLFILE_NOACCESS));\r
139     }\r
140   }\r
141   QTextStream outCore(&vhdlCore);\r
142   QTextStream outController;\r
143   if (genController) {\r
144     outController.setDevice(&vhdlController);\r
145   }\r
146 \r
147   try {\r
148 \r
149 \r
150     //Get the root element\r
151     QDomElement impl = document.documentElement();\r
152     QDomElement eltComments = impl.firstChildElement("comments");\r
153     generateComments(eltComments, coreFile, outCore);\r
154     QDomElement eltLibs = eltComments.nextSiblingElement("libraries");\r
155     generateLibraries(eltLibs, outCore);\r
156     generateEntity(outCore, genController);\r
157     QDomElement eltArch = eltLibs.nextSiblingElement("architecture");\r
158     generateArchitecture(eltArch, outCore);\r
159     if (genController) {\r
160       generateController(outController);\r
161     }\r
162   }\r
163   catch(Exception err) {\r
164     throw(err);\r
165   }\r
166 \r
167   vhdlCore.close();\r
168   vhdlController.close();\r
169 }\r
170 \r
171 // This function generates the comments part of the VHDL document\r
172 void BlockImplementation::generateComments(QDomElement &elt, QString coreFile, QTextStream& out) throw(Exception) {\r
173 \r
174   for(int i = 0; i < 50; i++) {\r
175     out << "--";\r
176   }\r
177   out << "\n--\n";\r
178   QString fileName = coreFile;\r
179   out << "--  File        : " << fileName << "\n";\r
180   out << "--\n";\r
181   QDomElement eltAuthor = elt.firstChildElement("author");\r
182   QString firstName = eltAuthor.attribute("firstname","");\r
183   QString lastName = eltAuthor.attribute("lastname","");\r
184   QString mail = eltAuthor.attribute("mail","");\r
185   out << "--  Author(s)   : "<<firstName+" "<<lastName<<" ("<<mail<<")\n";\r
186   out << "--\n";\r
187   QDomElement eltDate = eltAuthor.nextSiblingElement("date");\r
188   QString crea = eltDate.attribute("creation","");\r
189   out << "--  Creation Date   : "<<crea<<"\n";\r
190   out << "--\n";\r
191   QDomElement eltRelated = eltDate.nextSiblingElement("related_files");\r
192   QString relateds = eltRelated.attribute("list","");\r
193   out << "--  Related files   :\n"<<relateds<<"\n";\r
194   out << "--\n";\r
195   QDomElement eltDesc = eltRelated.nextSiblingElement("description");\r
196   QDomElement desc = eltDesc.firstChildElement();\r
197   QString descTxt = desc.text();\r
198   out << "--  Decription      :\n"<<descTxt<<"\n";\r
199   out << "--\n";\r
200   QDomElement eltNote = eltDesc.nextSiblingElement("description");\r
201   QDomElement note = eltNote.firstChildElement();\r
202   QString noteTxt = note.text();\r
203   out << "--  Note          :\n"<<noteTxt<<"\n";\r
204   out << "--\n";\r
205   for(int i = 0; i < 50; i++) {\r
206     out << "--";\r
207   }\r
208   out << "\n\n";\r
209 }\r
210 \r
211 // This function generates the library part of the VHDL document\r
212 void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception) {\r
213 \r
214   QDomNodeList listLib = elt.elementsByTagName("library");\r
215   for(int i = 0; i < listLib.length(); i++) {\r
216     QDomNode nodeLib = listLib.item(i);\r
217     QDomElement eltLib = nodeLib.toElement();\r
218     QString nameLib = eltLib.attribute("name", "");\r
219     out << "library " << nameLib << ";\n";\r
220     QDomNodeList listPack = eltLib.elementsByTagName("package");\r
221     for(int j = 0; j < listPack.length(); j++) {\r
222       QDomNode nodePack = listPack.item(j);\r
223       QDomElement eltPack = nodePack.toElement();\r
224       QString namePack = eltPack.attribute("name", "");\r
225       QString usePack = elt.attribute("use","");\r
226       out << "use " << nameLib << "." << namePack << "." << usePack << ";\n";\r
227     }\r
228     out << "\n";\r
229   }\r
230 }\r
231 \r
232 // This function generates the entity part of the VHDL document\r
233 void BlockImplementation::generateEntity(QTextStream& out, bool hasController) throw(Exception) {\r
234 \r
235   int i=0;\r
236   nameEnt = reference->getName();\r
237   //QList<BlockParameter*> listParams = reference->getParameters();\r
238   QList<AbstractInterface*> listInputs = reference->getInputs();\r
239   QList<AbstractInterface*> listOutputs = reference->getOutputs();\r
240   QList<AbstractInterface*> listBidirs = reference->getBidirs();\r
241   QString typePort, namePort;\r
242 \r
243   out << "entity " << nameEnt << " is\n";\r
244 \r
245 \r
246   /* TODO : rewrite the generation to take into acocunt the new object hierarchy */\r
247 \r
248   // Generation of the generics\r
249   QList<BlockParameter*> listGenerics = reference->getGenericParameters();\r
250   if ((!listGenerics.isEmpty()) || (hasController)) {\r
251     out << "  generic (" << endl;\r
252     if (hasController) {\r
253       out << "    wb_data_width : integer = 16;" << endl;\r
254       out << "    wb_addr_width : integer = 12";\r
255       if (!listGenerics.isEmpty()) out << ";";\r
256       out << endl;\r
257     }\r
258     for(i=0;i<listGenerics.size()-1;i++) {\r
259       out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0);\r
260     }\r
261     out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
262 \r
263     out << "    );" << endl;\r
264   }\r
265 \r
266   out << "  port (" << endl;\r
267 \r
268   // Generation of the clk & rst signals\r
269   out << "    -- clk/rst" << endl;\r
270   for(int i = 0; i < listInputs.size(); i++) {\r
271     if(listInputs.at(i)->getPurpose() == AbstractInterface::Clock || listInputs.at(i)->getPurpose() == AbstractInterface::Reset) {\r
272       out << "    " << listInputs.at(i)->getName() << " : in std_logic;" << endl;\r
273     }\r
274   }\r
275 \r
276   if (hasController) {\r
277     // Generation of the wishbone signals\r
278     out << "    -- registers r/w via wishbone" << endl;\r
279     QList<BlockParameter*> listWB = reference->getWishboneParameters();\r
280     for(i=0;i<listWB.size()-1;i++) {\r
281       out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity, 0);\r
282     }\r
283     out << "    " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma);\r
284   }\r
285 \r
286 \r
287   // Generation of the data signals\r
288   out << "-- data ports\n";\r
289   for(int i = 0; i < listInputs.size(); i++) {\r
290     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listInputs.at(i)->getName()));\r
291     if(listInputs.at(i)->getWidth().compare("1"))\r
292       typePort = "std_logic";\r
293     else\r
294       typePort = calculateWidth(listInputs.at(i)->getWidth());\r
295     if(listInputs.at(i)->getPurpose() == 1)\r
296       out << namePort << " : in std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
297   }\r
298 \r
299   for(int i = 0; i < listOutputs.size(); i++) {\r
300     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listOutputs.at(i)->getName()));\r
301     if(listOutputs.at(i)->getWidth().compare("1"))\r
302       typePort = "std_logic";\r
303     else\r
304       typePort = calculateWidth(listOutputs.at(i)->getWidth());\r
305     if(listOutputs.at(i)->getPurpose() == 1)\r
306       out << namePort << " : out std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
307   }\r
308 \r
309   for(int i = 0; i < listBidirs.size(); i++) {\r
310     namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listBidirs.at(i)->getName()));\r
311     if(listBidirs.at(i)->getWidth().compare(("1")))\r
312       typePort = "std_logic";\r
313     else\r
314       typePort = calculateWidth((listBidirs.at(i)->getWidth()));\r
315     if(listBidirs.at(i)->getPurpose() == 1)\r
316       out << namePort << " : inout std_logic_vector(" << typePort << " -1 downto 0) ;\n";\r
317   }\r
318 }\r
319 \r
320 // This function generates the architecture part of the VHDL document\r
321 void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception) {\r
322 \r
323   QString expr;\r
324   QDomElement eltArch = elt.nextSiblingElement("architecture");\r
325   out << "architecture " << nameEnt <<"_1 of " << nameEnt << "is\n";\r
326   QString implText = eltArch.text();\r
327   QStringList listLine = implText.split("\n");\r
328   for(int i =0; i < listLine.size(); i++) {\r
329     if(listLine.at(i).contains(QRegularExpression("@foreach{")) != -1) {\r
330       while(listLine.at(i).compare("@endforeach") != -1) {\r
331         expr = expr + listLine.at(i) + '\n';\r
332         i++;\r
333       }\r
334       expr = expr + listLine.at(i);\r
335       out << evalComplex(expr, 1) << '\n';\r
336     }\r
337     if(listLine.at(i).contains(QRegularExpression("@caseeach{")) != -1) {\r
338       while(listLine.at(i).compare("@endcaseeach") != -1) {\r
339         expr = expr + listLine.at(i) + '\n';\r
340         i++;\r
341       }\r
342       expr = expr + listLine.at(i);\r
343       out << evalComplex(expr, 2) << '\n';\r
344     }\r
345 \r
346     if(listLine.at(i).contains('@') == -1)\r
347       out << listLine.at(i) << "\n";\r
348     else\r
349       out << eval(listLine.at(i), out) << "\n";\r
350   }\r
351 }\r
352 \r
353 void BlockImplementation::generateController(QTextStream &out) throw(Exception) {\r
354 }\r
355 \r
356 QString BlockImplementation::eval(QString line, QTextStream& out) {\r
357   QString res, s, begLine, endLine, expr;\r
358   evaluator->setExpression(line);\r
359   QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
360   QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
361   QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
362 \r
363   int nbAt = line.count('@');\r
364   while(nbAt != 0) {\r
365     for(int i = 0; i < line.size(); i++) {\r
366       if(rxString->indexIn(line)) {\r
367         begLine = rxString->cap(1);\r
368         s = rxString->cap(2);\r
369         endLine = rxString->cap(3);\r
370         res = begLine + evalString(s) + endLine + '\n';\r
371         nbAt --;\r
372       }\r
373     }\r
374     for(int i = 0; i < line.size(); i++) {\r
375       if(rxValue->indexIn(line)) {\r
376         begLine = rxValue->cap(1);\r
377         s = rxValue->cap(2);\r
378         endLine = rxValue->cap(3);\r
379         res = begLine + evalValue(s) + endLine + '\n';\r
380         nbAt --;\r
381       }\r
382     }\r
383     for(int i = 0; i < line.size(); i++) {\r
384       if(rxExpr->indexIn(line)) {\r
385         expr = rxExpr->cap(1);\r
386         if(expr.count('@') == 0) {\r
387           evaluator->setExpression(expr);\r
388           s = QString::number(evaluator->evaluate());\r
389         }\r
390         res = begLine + s + endLine + '\n';\r
391         nbAt --;\r
392       }\r
393     }\r
394   }\r
395   return res;\r
396 }\r
397 \r
398 QString BlockImplementation::evalComplex(QString line, int id) {\r
399   QString res, s, begLine, endLine, expr;\r
400   QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)");\r
401   QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)");\r
402   QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*");\r
403   QRegExp *rxFor = new QRegExp("@foreach{.*}(@{.*})(.*)@endforeach");\r
404   QRegExp *rxCase = new QRegExp("@caseeach{.*,(.*),(.*)}(@{.*})(.*)@endcaseeach");\r
405   QRegExp *rxCaseDown = new QRegExp("@#-:(.*)");\r
406   QRegExp *rxCaseUp = new QRegExp("@#:(.*)");\r
407   evaluator->setExpression(line);\r
408 \r
409   int nbAt = line.count('@') - 2;\r
410   while(nbAt != 0) {\r
411     for(int i = 0; i < line.size(); i++) {\r
412       if(rxString->indexIn(line)) {\r
413         begLine = rxString->cap(1);\r
414         s = rxString->cap(2);\r
415         endLine = rxString->cap(3);\r
416         if(evalStringComplex(s)->size() == 0)\r
417           line = begLine + evalString(s) + endLine;\r
418         nbAt --;\r
419       }\r
420     }\r
421     for(int i = 0; i < line.size(); i++) {\r
422       if(rxValue->indexIn(line)) {\r
423         begLine = rxValue->cap(1);\r
424         s = rxValue->cap(2);\r
425         endLine = rxValue->cap(3);\r
426         line = begLine + evalValue(s) + endLine;\r
427         nbAt --;\r
428       }\r
429     }\r
430     for(int i = 0; i < line.size(); i++) {\r
431       if(rxExpr->indexIn(line)) {\r
432         expr = rxExpr->cap(1);\r
433         if(expr.count('@') == 0) {\r
434           evaluator->setExpression(expr);\r
435           s = QString::number(evaluator->evaluate());\r
436         }\r
437         res = begLine + s + endLine + '\n';\r
438         nbAt --;\r
439       }\r
440     }\r
441   }\r
442 \r
443   if(id == 1) {\r
444     if(rxFor->indexIn(line)) {\r
445       QString intName, instruc;\r
446       intName = rxFor->cap(1);\r
447       instruc = rxFor->cap(2);\r
448       QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
449       if(intList->size() != 0) {\r
450         for(int i = 0; i < intList->size(); i++) {\r
451           res = intList->at(i)->getName() + instruc + '\n';\r
452         }\r
453       }\r
454     }\r
455   }\r
456 \r
457   else if(id == 2) {\r
458     if(rxCase->indexIn(line)) {\r
459       QString intName, sigName, cases, instruc;\r
460       int number;\r
461       sigName = rxCase->cap(1);\r
462       cases = rxCase->cap(2);\r
463       intName = rxCase->cap(3);\r
464       instruc = rxCase->cap(4);\r
465       QList<AbstractInterface*> *intList = evalStringComplex(intName);\r
466       int listSize = intList->count();\r
467       res = "case " + sigName + " is\n";\r
468       if(rxCaseUp->indexIn(cases)) {\r
469         number = rxCaseUp->cap(1).toInt();\r
470         for(int j = number; j < listSize; j++) {\r
471           if(listSize > 0) {\r
472             for(int i = 0; i < listSize; i++) {\r
473               res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
474             }\r
475           }\r
476           else\r
477             res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
478           number++;\r
479         }\r
480       }\r
481       if(rxCaseDown->indexIn(cases)) {\r
482         number = rxCaseDown->cap(1).toInt();\r
483         for(int j = number; j < listSize; j++) {\r
484           if(listSize > 0) {\r
485             for(int i = 0; i < listSize; i++) {\r
486               res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n";\r
487             }\r
488           }\r
489           else\r
490             res += "\twhen " + number + ' ' + intName + instruc + "\n";\r
491           number--;\r
492         }\r
493         res += "end case ;\n";\r
494       }\r
495     }\r
496   }\r
497   return res;\r
498 }\r
499 \r
500 QString BlockImplementation::evalString(QString s) {\r
501 \r
502   QString name = getIfaceUserName(block->AbstractBlock::getIfaceFromName(s));\r
503   return name;\r
504 }\r
505 \r
506 QList<AbstractInterface*>* BlockImplementation::evalStringComplex(QString s) {\r
507 \r
508   int j = 0;\r
509   QList<AbstractInterface*> *listInterfaces = new QList<AbstractInterface*>();\r
510   AbstractInterface *inter = block->AbstractBlock::getIfaceFromName(s);\r
511   QList<AbstractInterface*> listIntBlock = block->getInterfaces();\r
512   for(int i = 0; i < listIntBlock.size(); i++) {\r
513     if(inter->getName().compare(listIntBlock.at(i)->getName()) < -1) {\r
514       listInterfaces->insert(j, inter);\r
515       j ++;\r
516     }\r
517   }\r
518   return listInterfaces;\r
519 }\r
520 \r
521 QString BlockImplementation::evalValue(QString s) {\r
522 \r
523   QString val = "";\r
524   if(paramMap.contains(s))\r
525     val = paramMap.value(s);\r
526   return val;\r
527 }\r
528 \r
529 QString BlockImplementation::getIfaceUserName(AbstractInterface* refIface) {\r
530 \r
531   if (! refIface->isReferenceInterface()) return "";\r
532 \r
533   AbstractInterface* funcIface = NULL;\r
534 \r
535   if (refIface->getDirection() == AbstractInterface::Input) {\r
536     foreach(AbstractInterface* iface, block->getInputs()) {\r
537       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
538       if (fi->getReference() == refIface) {\r
539         funcIface = iface;\r
540         break;\r
541       }\r
542     }\r
543   }\r
544   else if (refIface->getDirection() == AbstractInterface::Output) {\r
545     foreach(AbstractInterface* iface, block->getOutputs()) {\r
546       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
547       if (fi->getReference() == refIface) {\r
548         funcIface = iface;\r
549         break;\r
550       }\r
551     }\r
552   }\r
553   else if (refIface->getDirection() == AbstractInterface::InOut) {\r
554     foreach(AbstractInterface* iface, block->getBidirs()) {\r
555       FunctionalInterface* fi = (FunctionalInterface*)iface;\r
556       if (fi->getReference() == refIface) {\r
557         funcIface = iface;\r
558         break;\r
559       }\r
560     }\r
561   }\r
562   if (funcIface == NULL) return "";\r
563 \r
564   return funcIface->getName();\r
565 }\r
566 \r
567 QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) {\r
568 \r
569   out.setVersion(QDataStream::Qt_5_0);\r
570 \r
571   QByteArray blockData;\r
572   QDataStream toWrite(&blockData, QIODevice::WriteOnly);\r
573 \r
574   toWrite << impl.xmlFile;\r
575   toWrite << impl.referenceXml;\r
576   toWrite << impl.referenceMd5;\r
577   // saving patterns\r
578   toWrite << impl.delta;\r
579   toWrite << impl.consumptionPattern;\r
580   toWrite << impl.productionPattern;\r
581   toWrite << impl.productionCounter;\r
582   \r
583   out << blockData;\r
584 \r
585   return out;\r
586 }\r
587 \r
588 QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) {\r
589 \r
590   quint32 blockSize;\r
591 \r
592   in.setVersion(QDataStream::Qt_5_0);\r
593 \r
594   in >> blockSize;\r
595 \r
596   in >> impl.xmlFile;\r
597   in >> impl.referenceXml;\r
598   in >> impl.referenceMd5;\r
599   // loading patterns\r
600   in >> impl.delta;\r
601   in >> impl.consumptionPattern;\r
602   in >> impl.productionPattern;\r
603   in >> impl.productionCounter;\r
604 \r
605   return in;\r
606 }\r
607 \r
608 QString BlockImplementation::calculateWidth(QString s){\r
609   QRegExp *rxWidth = new QRegExp("$*([a-zA-Z0-9_-]*)");\r
610   QStringList matchList = s.split(" ");\r
611   int pos = 0;\r
612   QString res, line;\r
613   QList<BlockParameter*> listParams = reference->getParameters();\r
614 \r
615   while ((pos = rxWidth->indexIn(s, pos)) != -1) {\r
616     matchList << rxWidth->cap(1);\r
617     pos += rxWidth->matchedLength();\r
618   }\r
619 \r
620   for (int i = 0; i < matchList.size(); i++) {\r
621     QString match = matchList.at(i);\r
622     if(rxWidth->indexIn(match)) {\r
623       for(int j = 0; j < listParams.size(); j++) {\r
624         if(match.compare(listParams.at(j)->getName())) {\r
625           BlockParameter *param = listParams.at(i);\r
626           if(param->getContext() == "generic") {\r
627             match = match.remove('$');\r
628           }\r
629           else {\r
630             match = param->getValue().toString();\r
631           }\r
632         }\r
633       }\r
634     }\r
635   }\r
636   line = matchList.join(' ');\r
637   evaluator->setExpression(line);\r
638   res = evaluator->evaluate();\r
639   return res;\r
640 }\r
641 \r