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

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