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

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