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

Private GIT Repository
finished testbench generation
[blast.git] / VHDLConverter.cpp
1 #include "VHDLConverter.h"\r
2 #include "BlockParameterGeneric.h"\r
3 #include "BlockParameterUser.h"\r
4 #include "BlockParameterWishbone.h"\r
5 #include "ReferenceInterface.h"\r
6 \r
7 using namespace std;\r
8 using namespace Qt;\r
9 \r
10 VHDLConverter::VHDLConverter(QWidget *parent) : QWidget(parent) {\r
11 \r
12   QLabel *labelAppli, *lblBrief, *lblDesc, *lblEntName, *lblLongName, *lblPort, *lblGen;\r
13 \r
14   loadBut = new QPushButton("load VHDL");\r
15   genBut = new QPushButton("generate XML");\r
16   QHBoxLayout *widgetLayout = new QHBoxLayout;\r
17   QVBoxLayout *left = new QVBoxLayout;\r
18   QVBoxLayout *right = new QVBoxLayout;\r
19 \r
20   scrollPorts = new QScrollArea;\r
21   scrollPorts->setWidgetResizable(true);\r
22   twPorts = new QTableWidget(this);\r
23   twPorts->setColumnCount(5);\r
24   scrollPorts->setWidget(twPorts);\r
25   scrollGenerics = new QScrollArea;\r
26   scrollGenerics->setWidgetResizable(true);\r
27   twGenerics = new QTableWidget(this);\r
28   twGenerics->setColumnCount(3);\r
29   scrollGenerics->setWidget(twGenerics);\r
30   editEntityName = new QLineEdit;\r
31   editLongName = new QLineEdit;\r
32   teBrief = new QTextEdit;\r
33   teDesc = new QTextEdit;\r
34   lblEntName = new QLabel("Entity name :");\r
35   lblLongName = new QLabel("Block long name :");\r
36   lblBrief = new QLabel("Enter a brief description : ");\r
37   lblDesc = new QLabel("Enter a detailled description : ");\r
38   lblPort = new QLabel("Ports :");\r
39   lblGen = new QLabel("Generics :");\r
40 \r
41   connect(loadBut, SIGNAL(clicked()),this, SLOT(loadVHDLFile()));\r
42   connect(genBut, SIGNAL(clicked()), this, SLOT(generateXml()));\r
43 \r
44   left->addWidget(loadBut);\r
45   left->addWidget(lblPort);\r
46   left->addWidget(scrollPorts);\r
47   left->addWidget(lblGen);\r
48   left->addWidget(scrollGenerics);\r
49 \r
50   right->addWidget(lblEntName);\r
51   right->addWidget(editEntityName);\r
52   right->addWidget(lblLongName);\r
53   right->addWidget(editLongName);\r
54   right->addWidget(lblBrief);\r
55   right->addWidget(teBrief);\r
56   right->addWidget(lblDesc);\r
57   right->addWidget(teDesc);\r
58   right->addWidget(genBut);\r
59 \r
60   widgetLayout->addLayout(left);\r
61   widgetLayout->addLayout(right);\r
62   setLayout(widgetLayout);\r
63   show();\r
64 }\r
65 \r
66 VHDLConverter::~VHDLConverter() {\r
67 \r
68 }\r
69 \r
70 QString VHDLConverter::skipBlankAndComments(QTextStream &in) {\r
71   \r
72   QString line = "";\r
73   \r
74   // skipping blank/comment lines\r
75   while ( (line.isEmpty()) || ((line.at(0) == '-') && (line.at(1) == '-')) ) {\r
76     if (in.atEnd()) {\r
77       return "";\r
78     }\r
79     line = in.readLine();\r
80     if (!line.isEmpty()) line = line.simplified();\r
81   }\r
82   line.remove(QRegularExpression("--.*$"));\r
83   return line;\r
84 }\r
85 \r
86 QString VHDLConverter::readLibraries(QTextStream &in) throw(Exception) {\r
87   \r
88   QRegularExpression rxLib("^library[\\s\\t]*(.+);$",QRegularExpression::CaseInsensitiveOption);\r
89   QRegularExpression rxPack("^use[\\s\\t]*([^.]+)[.](.+);$",QRegularExpression::CaseInsensitiveOption);\r
90   QString line = "";\r
91   \r
92   line = skipBlankAndComments(in);\r
93   if (line == "") {\r
94     throw(Exception(VHDLFILE_CORRUPTED));\r
95   }\r
96   \r
97   while (! line.contains("entity",Qt::CaseInsensitive)) {\r
98     \r
99     QRegularExpressionMatch matchLib = rxLib.match(line);\r
100     QRegularExpressionMatch matchPack = rxPack.match(line);\r
101     \r
102     if (matchLib.hasMatch()) {\r
103       \r
104       QString libName = matchLib.captured(1);\r
105       libName = libName.toLower();\r
106       \r
107       cout << "matching library: " << qPrintable(libName) << endl;\r
108       \r
109       if (!packages.contains(libName)) {\r
110         packages.insert(libName,new QList<QString>());\r
111       }\r
112     }\r
113     else if (matchPack.hasMatch()) {\r
114       cout << "matching packages" << endl;\r
115       \r
116       QString libName = matchPack.captured(1);\r
117       QString packName = matchPack.captured(2);\r
118       \r
119       libName = libName.toLower();\r
120       packName = packName.toLower();\r
121 \r
122       if (libName == "work") {\r
123         if (!packages.contains("work")) {\r
124           packages.insert("work",new QList<QString>());\r
125         }\r
126       }\r
127       else if (libName == "std") {\r
128         if (!packages.contains("std")) {\r
129           packages.insert("std",new QList<QString>());\r
130         }\r
131       }\r
132       else if (!packages.contains(libName)) throw(Exception(VHDLFILE_CORRUPTED));\r
133       \r
134       QList<QString>* lstPack = packages.value(libName);\r
135       lstPack->append(packName);\r
136       cout << qPrintable(packName) << endl;\r
137       \r
138     }\r
139     \r
140     line = skipBlankAndComments(in);\r
141     if (line == "") {\r
142       throw(Exception(VHDLFILE_CORRUPTED));\r
143     }\r
144     cout << "read line = " << qPrintable(line) << endl;\r
145   }\r
146 \r
147   return line;\r
148 }\r
149 \r
150 QString VHDLConverter::readEntity(QTextStream &in) throw(Exception) {\r
151 \r
152   QRegularExpression rxGen("^generic[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);\r
153   QRegularExpression rxPorts("^port[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);\r
154 \r
155   QString line = "";\r
156 \r
157   line = skipBlankAndComments(in);\r
158   if (line == "") {\r
159     throw(Exception(VHDLFILE_CORRUPTED));\r
160   }\r
161 \r
162   while (! line.startsWith("architecture",Qt::CaseInsensitive)) {\r
163 \r
164     QRegularExpressionMatch matchGen = rxGen.match(line);\r
165     QRegularExpressionMatch matchPorts = rxPorts.match(line);\r
166 \r
167     if (matchGen.hasMatch()) {\r
168       cout << "matching generics" << endl;\r
169       if (matchGen.captured(1).length() > 0) {\r
170         cerr << "Please, modify VHDL source so that the generic list does not begin at the same line as generic (" << endl;\r
171         throw(Exception(VHDLFILE_CORRUPTED));\r
172       }\r
173       readGenerics(in);\r
174     }\r
175     else if (matchPorts.hasMatch()) {\r
176       cout << "matching ports" << endl;\r
177       if (matchPorts.captured(1).length() > 0) {\r
178         cerr << "Please, modify VHDL source so that the port list does not begin at the same line as port (" << endl;\r
179         throw(Exception(VHDLFILE_CORRUPTED));\r
180       }\r
181       readPorts(in);\r
182     }\r
183 \r
184     line = skipBlankAndComments(in);\r
185     if (line == "") {\r
186       throw(Exception(VHDLFILE_CORRUPTED));\r
187     }\r
188     cout << "read line = " << qPrintable(line) << endl;\r
189   }\r
190 \r
191   return line;\r
192 }\r
193 \r
194 void VHDLConverter::readGenerics(QTextStream &in) throw(Exception) {\r
195 \r
196   QRegularExpression rxGen("^([^:]+):([^:]+)(:=)?([^;]*);?$",QRegularExpression::CaseInsensitiveOption);\r
197 \r
198   QString line = "";\r
199 \r
200   line = skipBlankAndComments(in);\r
201   if (line == "") {\r
202     throw(Exception(VHDLFILE_CORRUPTED));\r
203   }\r
204   line = line.remove(' ');\r
205 \r
206   while (! line.contains(QRegExp("\\);"))) {\r
207 \r
208     QRegularExpressionMatch matchGen = rxGen.match(line);\r
209 \r
210     if (matchGen.hasMatch()) {\r
211       cout << "matching generic value" << endl;\r
212       QString genName = matchGen.captured(1);\r
213       QString genType = matchGen.captured(2);\r
214       genType = genType.toLower();\r
215       QString genValue = matchGen.captured(4);\r
216       genValue = genValue.toLower();\r
217       cout << qPrintable(genName) << " " << qPrintable(genType) << " " << qPrintable(genValue) << endl;\r
218       BlockParameter* param = new BlockParameterGeneric(block,genName,genType,genValue);\r
219       block->addParameter(param);\r
220     }\r
221 \r
222     line = skipBlankAndComments(in);\r
223     if (line == "") {\r
224       throw(Exception(VHDLFILE_CORRUPTED));\r
225     }\r
226     line = line.remove(' ');\r
227     cout << "read line = " << qPrintable(line) << endl;\r
228   }\r
229 }\r
230 \r
231 void VHDLConverter::readPorts(QTextStream &in) throw(Exception) {\r
232 \r
233   QRegularExpression rxPort("^([^ :]+) ?: ?(in|out|inout) ([a-zA-Z0-9_]+) ?(\\([^:)]*\\))? ?(:=)? ?([^;]*) ?;?$",QRegularExpression::CaseInsensitiveOption);\r
234   QRegularExpression rxSizeDownTo("^\\((.*) downto (.*)\\)$",QRegularExpression::CaseInsensitiveOption);\r
235   QRegularExpression rxSizeTo("^\\((.*) to (.*)\\)$",QRegularExpression::CaseInsensitiveOption);\r
236 \r
237   QString line = "";\r
238 \r
239   line = skipBlankAndComments(in);\r
240   if (line == "") {\r
241     throw(Exception(VHDLFILE_CORRUPTED));\r
242   }\r
243 \r
244   while (! line.contains(QRegExp("^\\);$"))) {\r
245 \r
246     line = line.toLower();\r
247 \r
248     QRegularExpressionMatch matchPort = rxPort.match(line);\r
249 \r
250     if (matchPort.hasMatch()) {\r
251       cout << "matching port value" << endl;\r
252       QString portName = matchPort.captured(1);\r
253       QString portDir = matchPort.captured(2);\r
254       QString portType = matchPort.captured(3);\r
255       QString portSize = matchPort.captured(4);\r
256       QString portValue = matchPort.captured(6);\r
257       cout << qPrintable(portName) << "|" << qPrintable(portDir) << "|" << qPrintable(portType) << "|" << qPrintable(portSize) << "|" << qPrintable(portValue) << endl;\r
258       ReferenceInterface* iface = NULL;\r
259       bool isOk = true;\r
260       int direction = AbstractInterface::AnyDirection;\r
261       int endianess = AbstractInterface::LittleEndian;\r
262       int purpose = AbstractInterface::AnyPurpose;\r
263 \r
264       QString widthStr = "a";\r
265 \r
266       if (portDir == "in") {\r
267         direction = AbstractInterface::Input;\r
268       }\r
269       else if (portDir == "out") {\r
270         direction = AbstractInterface::Output;\r
271       }\r
272       else if (portDir == "inout") {\r
273         direction = AbstractInterface::InOut;\r
274       }\r
275       else {\r
276         cerr << "Unknown direction for port " << qPrintable(portName) << endl;\r
277         isOk = false;\r
278       }\r
279       QString typeStr="";\r
280       if (portType == "std_logic") {\r
281         typeStr = "boolean";\r
282         widthStr="1";\r
283       }\r
284       else if (portType == "std_logic_vector") {\r
285 \r
286         if (portSize.contains("downto")) {\r
287           QRegularExpressionMatch matchSize = rxSizeDownTo.match(portSize);\r
288           endianess = AbstractInterface::LittleEndian;\r
289           if (matchSize.captured(2) != "0") {\r
290             cerr << "invalid size for port " << qPrintable(portName) << endl;\r
291             isOk = false;\r
292           }\r
293           else {\r
294             widthStr = matchSize.captured(1);\r
295           }\r
296         }\r
297         else if (portSize.contains("to")) {\r
298           QRegularExpressionMatch matchSize = rxSizeTo.match(portSize);\r
299           endianess = AbstractInterface::BigEndian;\r
300           if (matchSize.captured(1) != "0") {\r
301             cerr << "invalid size for port " << qPrintable(portName) << endl;\r
302             isOk = false;\r
303           }\r
304           else {\r
305             widthStr = matchSize.captured(2);\r
306           }\r
307         }\r
308         else {\r
309           cerr << "invalid size for port " << qPrintable(portName) << endl;\r
310           isOk = false;\r
311         }\r
312 \r
313         QVariant msb(widthStr);\r
314         bool ok;\r
315         int size = msb.toInt(&ok);\r
316         if (ok) {\r
317           typeStr = "natural";\r
318         }\r
319         else {\r
320           typeStr ="expression";\r
321         }\r
322       }\r
323       else {\r
324         cerr << "Unknown type for port " << qPrintable(portName) << endl;\r
325         isOk = false;\r
326       }\r
327 \r
328       if (isOk) {\r
329         // trying to guess the purpose from name\r
330         if ((portName.contains("clk"))||(portName.contains("clock"))) {\r
331           purpose = AbstractInterface::Clock;\r
332         }\r
333         else if ((portName.contains("rst"))||(portName.contains("reset"))) {\r
334           purpose = AbstractInterface::Reset;\r
335         }\r
336         else if (portName.endsWith("_enb")) {\r
337           purpose = AbstractInterface::Control;\r
338         }\r
339         else if (portName.startsWith("wb_")) {\r
340           purpose = AbstractInterface::Wishbone;\r
341         }\r
342         else {\r
343           purpose = AbstractInterface::Data;\r
344         }\r
345         iface = new ReferenceInterface(block,portName,direction,purpose,typeStr,widthStr,endianess,1);\r
346         block->addInterface(iface);\r
347       }\r
348     }\r
349 \r
350     line = skipBlankAndComments(in);\r
351     if (line == "") {\r
352       throw(Exception(VHDLFILE_CORRUPTED));\r
353     }\r
354     cout << "read line = " << qPrintable(line) << endl;\r
355   }\r
356 \r
357 }\r
358 \r
359 void VHDLConverter::readArchitecture(QTextStream &in) throw(Exception) {\r
360 \r
361   QString line = "";\r
362   QString endLine1 = "end "+archName;\r
363   QString endLine2 = "end architecture "+archName;\r
364   bool stop = false;\r
365 \r
366   while (!stop) {\r
367     line = in.readLine();\r
368     if (!line.isEmpty()) line = line.simplified();\r
369     archLines.append(line);\r
370     if ((line.startsWith(endLine1)) || (line.startsWith(endLine2)) ) {\r
371       stop = true;\r
372     }\r
373   }  \r
374 }\r
375 \r
376 // This function opens a VHDL file and get the informations about the entity :\r
377 // First the generics, then the signals.\r
378 // You can edit the descriptions in the right, one for the brief description, the other for the detailled.\r
379 void VHDLConverter::loadVHDLFile() {\r
380 \r
381   QString fileName = QFileDialog::getOpenFileName(this,\r
382                                                   tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)"));\r
383   QFile file(fileName);\r
384 \r
385   if(!file.open(QIODevice::ReadOnly | QIODevice::Text))\r
386     return;\r
387   QTextStream ts(&file);\r
388 \r
389   block = new ReferenceBlock(fileName);\r
390 \r
391   QString entityLine = "";\r
392   try {\r
393     entityLine = readLibraries(ts);\r
394   }\r
395   catch(Exception e) {\r
396     cerr << "VHDL seems to be malformed" << endl;\r
397     return;\r
398   }\r
399 \r
400   QRegularExpression rxEnt("^entity (.+) is$",QRegularExpression::CaseInsensitiveOption);\r
401   QRegularExpressionMatch matchEnt = rxEnt.match(entityLine);\r
402   if (!matchEnt.hasMatch()) {\r
403     cerr << "VHDL seems to be malformed" << endl;\r
404     return;\r
405   }\r
406   entityName = matchEnt.captured(1);\r
407   cout << "found entity " << qPrintable(entityName) << endl;\r
408 \r
409   QString archLine = "";\r
410   try {\r
411     archLine = readEntity(ts);\r
412   }\r
413   catch(Exception e) {\r
414     cerr << "VHDL seems to be malformed" << endl;\r
415     return;\r
416   }\r
417 \r
418   QRegularExpression rxArch("^architecture (.+) of (.+) is$",QRegularExpression::CaseInsensitiveOption);\r
419   QRegularExpressionMatch matchArch = rxArch.match(archLine);\r
420   if (!matchArch.hasMatch()) {\r
421     cerr << "VHDL seems to be malformed" << endl;\r
422     return;\r
423   }\r
424   archName = matchArch.captured(1);\r
425   cout << "found arch " << qPrintable(archName) << " for entity " << qPrintable(matchArch.captured(2)) << endl;\r
426 \r
427   try {\r
428     readArchitecture(ts);\r
429   }\r
430   catch(Exception e) {\r
431     cerr << "VHDL seems to be malformed" << endl;\r
432     return;\r
433   }\r
434   file.close();\r
435 \r
436 \r
437   QList<BlockParameter*> lstGenerics = block->getGenericParameters();\r
438   twGenerics->setRowCount(lstGenerics.size());\r
439   int i = 0;\r
440   foreach(BlockParameter* param, lstGenerics) {\r
441     twGenerics->setItem(i, 0, new QTableWidgetItem(param->getName()));\r
442     twGenerics->setItem(i, 1, new QTableWidgetItem(param->getTypeString()));\r
443     twGenerics->setItem(i, 2, new QTableWidgetItem(param->getValue().toString()));\r
444     i++;\r
445   }\r
446 \r
447   lstIface = block->getInputs();\r
448   lstIface.append(block->getOutputs());\r
449   lstIface.append(block->getBidirs());\r
450 \r
451   twPorts->setRowCount(lstIface.size());\r
452   purposeDelegate = new IfacePurposeDelegate();\r
453   twPorts->setItemDelegateForColumn(3,purposeDelegate);\r
454 \r
455   i=0;\r
456   foreach(AbstractInterface* iface, lstIface) {\r
457     twPorts->setItem(i, 0, new QTableWidgetItem(iface->getName()));\r
458     twPorts->setItem(i, 1, new QTableWidgetItem(iface->getDirectionString()));\r
459     QString widthStr="";\r
460     if (iface->getType() == AbstractInterface::Boolean) {\r
461       widthStr = "std_logic";\r
462     }\r
463     else {\r
464       widthStr = "std_logic_vector(";\r
465       if (iface->getEndianess() == AbstractInterface::LittleEndian) {\r
466         widthStr += iface->getWidthString();\r
467         widthStr += " downto 0)";\r
468       }\r
469       else {\r
470         widthStr += "0 to ";\r
471         widthStr += iface->getWidthString();\r
472         widthStr += ")";\r
473       }\r
474     }\r
475     twPorts->setItem(i, 2, new QTableWidgetItem(widthStr));\r
476 \r
477     QTableWidgetItem* item = new QTableWidgetItem(iface->getPurposeString());\r
478     twPorts->setItem(i, 3, item);\r
479 \r
480     // trying to find wihch other iface this one controls\r
481     QString assoInter = "N/A";\r
482     if (iface->getPurpose() == AbstractInterface::Control) {\r
483       QString name = iface->getName();\r
484       name.remove(name.size()-4,4); // remove _enb at the end\r
485       foreach(AbstractInterface* inter, lstIface) {\r
486         if ((inter != iface) && (inter->getName().contains(name))) {\r
487           assoInter = inter->getName();\r
488           iface->setAssociatedIface(inter);\r
489         }\r
490       }\r
491     }\r
492     QTableWidgetItem* itemAsso = new QTableWidgetItem(assoInter);\r
493     if (iface->getPurpose() != AbstractInterface::Control) {\r
494       itemAsso->setFlags(Qt::NoItemFlags);\r
495     }\r
496     twPorts->setItem(i, 4, itemAsso);\r
497 \r
498     i++;\r
499   }\r
500 \r
501   connect(twPorts,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(searchAssociatedPort(QTableWidgetItem*)));\r
502 \r
503   //file.close();\r
504 \r
505   //scrollPorts->setWidget(twPorts);\r
506   editEntityName->setText(entityName);\r
507   editLongName->setText(entityName);\r
508   return;\r
509 }\r
510 \r
511 void VHDLConverter::searchAssociatedPort(QTableWidgetItem *item) {\r
512 \r
513   bool ok;\r
514   int col = item->column();\r
515   int row = item->row();\r
516 \r
517   // searching for the real interface object linked to the item\r
518   AbstractInterface* iface = NULL;\r
519   QString ifaceName = twPorts->item(row,0)->text();\r
520   foreach(AbstractInterface* inter,lstIface) {\r
521     if (inter->getName() == ifaceName) {\r
522       iface = inter;\r
523       break;\r
524     }\r
525   }\r
526 \r
527   if (col == 3) {\r
528 \r
529     QString assoInter = "N/A";\r
530     iface->setAssociatedIface(NULL);\r
531 \r
532     cout << qPrintable(item->text()) << endl;\r
533 \r
534     if (item->text() == "data") {\r
535       iface->setPurpose(AbstractInterface::Data);\r
536     }\r
537     else if (item->text() == "control") {\r
538       iface->setPurpose(AbstractInterface::Control);\r
539     }\r
540     else if (item->text() == "clock") {\r
541       iface->setPurpose(AbstractInterface::Clock);\r
542     }\r
543     else if (item->text() == "reset") {\r
544       iface->setPurpose(AbstractInterface::Reset);\r
545     }\r
546     else if (item->text() == "wishbone") {\r
547       iface->setPurpose(AbstractInterface::Wishbone);\r
548     }\r
549 \r
550     if (item->text() == "control") {\r
551 \r
552       QString name = twPorts->item(row,0)->text();\r
553       name.remove(name.size()-4,4); // remove _enb at the end\r
554       int i=0;\r
555       foreach(AbstractInterface* inter, lstIface) {\r
556         if ((i != row) && (inter->getName().contains(name))) {\r
557           assoInter = inter->getName();\r
558           iface->setAssociatedIface(inter);\r
559         }\r
560         i++;\r
561       }\r
562     }\r
563 \r
564     QTableWidgetItem* itemAsso = twPorts->item(row,4);\r
565     itemAsso->setText(assoInter);\r
566 \r
567     if (item->text() == "control") {\r
568       itemAsso->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable);\r
569     }\r
570     else {\r
571       itemAsso->setFlags(Qt::NoItemFlags);\r
572     }\r
573   }\r
574   else if (col == 4) {\r
575 \r
576     QString nameAsso = item->text();\r
577     if (nameAsso == "N/A") return;\r
578 \r
579     bool found = false;\r
580 \r
581     int i=0;\r
582     foreach(AbstractInterface* inter, lstIface) {\r
583       if ((i != row) && (inter->getName().contains(nameAsso))) {\r
584         found = true;\r
585         iface->setAssociatedIface(inter);\r
586       }\r
587     }\r
588     if (!found) {\r
589       QTableWidgetItem* itemAsso = twPorts->item(row,4);\r
590       itemAsso->setText("N/A");\r
591     }\r
592   }\r
593 }\r
594 \r
595 void VHDLConverter::generateRefXml(QDomDocument& doc) {\r
596 \r
597   QDomElement eBlock = doc.createElement("block");\r
598   eBlock.setAttribute("version", "0.1");\r
599   doc.appendChild(eBlock);\r
600 \r
601   // creating infos\r
602   QDomElement infos = doc.createElement("informations");\r
603   eBlock.appendChild(infos);\r
604 \r
605   QDomElement eName = doc.createElement("name");\r
606   QDomText tName = doc.createTextNode(editLongName->text());\r
607   eName.appendChild(tName);\r
608   infos.appendChild(eName);\r
609 \r
610   QDomElement category = doc.createElement("category");\r
611   category.setAttribute("ids","");\r
612   infos.appendChild(category);\r
613 \r
614   QDomElement eDesc = doc.createElement("description");\r
615   QString brief = teBrief->toPlainText();\r
616   QString detailed = teDesc->toPlainText();\r
617   QDomElement eBrief = doc.createElement("brief");\r
618   if(!brief.isEmpty()) {\r
619     QDomText txtBrief = doc.createTextNode(brief);\r
620     eBrief.appendChild(txtBrief);\r
621     eDesc.appendChild(eBrief);\r
622   }\r
623   QDomElement eDetailed = doc.createElement("detailed");\r
624   if(!detailed.isEmpty()) {\r
625     QDomText txtDetailed = doc.createTextNode(detailed);\r
626     eDetailed.appendChild(txtDetailed);\r
627     eDesc.appendChild(eDetailed);\r
628   }\r
629   infos.appendChild(eDesc);\r
630 \r
631 \r
632 \r
633   QDomElement parameters = doc.createElement("parameters");\r
634   eBlock.appendChild(parameters);\r
635 \r
636   QList<BlockParameter*> lstGenerics = block->getGenericParameters();\r
637   foreach(BlockParameter* param, lstGenerics) {\r
638     QDomElement parameter = doc.createElement("parameter");\r
639     parameter.setAttribute("name",param->getName());\r
640     parameter.setAttribute("type",param->getTypeString());\r
641     parameter.setAttribute("value",param->getValue().toString());\r
642     parameter.setAttribute("context","generic");\r
643     parameters.appendChild(parameter);\r
644   }\r
645 \r
646   QDomElement interfaces = doc.createElement("interfaces");\r
647   eBlock.appendChild(interfaces);\r
648 \r
649   if (block->getInputs().size() > 0) {\r
650     QDomElement inputs = doc.createElement("inputs");\r
651     interfaces.appendChild(inputs);\r
652     foreach(AbstractInterface* iface, block->getInputs()) {\r
653 \r
654       if (iface->getPurpose() != AbstractInterface::Control) {\r
655         QDomElement input = doc.createElement("input");\r
656         input.setAttribute("name",iface->getName());\r
657         input.setAttribute("type",iface->getTypeString());\r
658         input.setAttribute("width",iface->getWidthString());\r
659         input.setAttribute("multiplicity","1");\r
660         input.setAttribute("purpose",iface->getPurposeString());\r
661         input.setAttribute("endian",iface->getEndianessString());\r
662         inputs.appendChild(input);\r
663       }\r
664       else {\r
665         QDomElement ctl = doc.createElement("control");\r
666         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
667         inputs.appendChild(ctl);\r
668       }\r
669     }\r
670   }\r
671 \r
672   if (block->getOutputs().size() > 0) {\r
673     QDomElement outputs = doc.createElement("outputs");\r
674     interfaces.appendChild(outputs);\r
675     foreach(AbstractInterface* iface, block->getOutputs()) {\r
676       if (iface->getPurpose() != AbstractInterface::Control) {\r
677         QDomElement output = doc.createElement("output");\r
678         output.setAttribute("name",iface->getName());\r
679         output.setAttribute("type",iface->getTypeString());\r
680         output.setAttribute("width",iface->getWidthString());\r
681         output.setAttribute("multiplicity","1");\r
682         output.setAttribute("purpose",iface->getPurposeString());\r
683         output.setAttribute("endian",iface->getEndianessString());\r
684         outputs.appendChild(output);\r
685       }\r
686       else {\r
687         QDomElement ctl = doc.createElement("control");\r
688         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
689         outputs.appendChild(ctl);\r
690       }\r
691     }\r
692   }\r
693 \r
694   if (block->getBidirs().size() > 0) {\r
695     QDomElement bidirs = doc.createElement("bidirs");\r
696     interfaces.appendChild(bidirs);\r
697     foreach(AbstractInterface* iface, block->getBidirs()) {\r
698       if (iface->getPurpose() != AbstractInterface::Control) {\r
699         QDomElement bidir = doc.createElement("bidir");\r
700         bidir.setAttribute("name",iface->getName());\r
701         bidir.setAttribute("type",iface->getTypeString());\r
702         bidir.setAttribute("width",iface->getWidthString());\r
703         bidir.setAttribute("multiplicity","1");\r
704         bidir.setAttribute("purpose",iface->getPurposeString());\r
705         bidir.setAttribute("endian",iface->getEndianessString());\r
706         bidirs.appendChild(bidir);\r
707       }\r
708       else {\r
709         QDomElement ctl = doc.createElement("control");\r
710         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
711         bidirs.appendChild(ctl);\r
712       }\r
713     }\r
714   }\r
715 }\r
716 \r
717 void VHDLConverter::generateImplXml(QDomDocument& doc) {\r
718 \r
719   QRegularExpression rxPack("^([^.]+)[.](.+)$",QRegularExpression::CaseInsensitiveOption);\r
720 \r
721   QDomElement eBlock = doc.createElement("block_impl");\r
722   eBlock.setAttribute("ref_name", entityName+".xml");\r
723   eBlock.setAttribute("ref_md5", "");\r
724   doc.appendChild(eBlock);\r
725 \r
726   // creating infos\r
727   QDomElement comments = doc.createElement("comments");\r
728   eBlock.appendChild(comments);\r
729 \r
730   QDomElement author = doc.createElement("author");\r
731   author.setAttribute("firstname","");\r
732   author.setAttribute("lastname","");\r
733   author.setAttribute("mail","");\r
734   comments.appendChild(author);\r
735 \r
736   QDomElement date = doc.createElement("date");\r
737   date.setAttribute("creation","");\r
738   comments.appendChild(date);\r
739 \r
740   QString brief = teBrief->toPlainText();\r
741   QString detailed = teDesc->toPlainText();\r
742   QDomElement eDesc = doc.createElement("description");\r
743   if(!brief.isEmpty()) {\r
744     QDomText txtBrief = doc.createTextNode(brief);\r
745     eDesc.appendChild(txtBrief);\r
746     comments.appendChild(eDesc);\r
747   }\r
748   QDomElement eNotes = doc.createElement("notes");\r
749   if(!detailed.isEmpty()) {\r
750     QDomText txtDetailed = doc.createTextNode(detailed);\r
751     eNotes.appendChild(txtDetailed);\r
752     comments.appendChild(eNotes);\r
753   }\r
754 \r
755   QDomElement libs = doc.createElement("libraries");\r
756   eBlock.appendChild(libs);\r
757 \r
758   QHashIterator<QString,QList<QString>* > it(packages);\r
759 \r
760   while (it.hasNext()) {\r
761     it.next();\r
762     QString libName = it.key();\r
763     cout << qPrintable(libName) << endl;\r
764     QList<QString>* packList = it.value();\r
765     QDomElement lib = doc.createElement("library");\r
766     lib.setAttribute("name", libName);\r
767     libs.appendChild(lib);\r
768 \r
769     foreach(QString packName, *packList) {\r
770       QDomElement pack = doc.createElement("package");\r
771       lib.appendChild(pack);\r
772       QRegularExpressionMatch matchPack = rxPack.match(packName);\r
773       if (matchPack.hasMatch()) {\r
774         QString name = matchPack.captured(1);\r
775         QString subName = matchPack.captured(2);\r
776         name = name.toLower();\r
777         subName = subName.toLower();\r
778         pack.setAttribute("name",name);\r
779         pack.setAttribute("use",subName);\r
780       }\r
781     }\r
782   }\r
783 \r
784   QDomElement archi = doc.createElement("architecture");\r
785   eBlock.appendChild(archi);\r
786   QDomText tName = doc.createTextNode("");\r
787   foreach(QString line, archLines) {\r
788     tName.appendData(line+"\n");\r
789   }\r
790   archi.appendChild(tName);\r
791 \r
792   QDomElement patterns = doc.createElement("patterns");\r
793   eBlock.appendChild(patterns);\r
794   QDomElement delta = doc.createElement("delta");\r
795   delta.setAttribute("value","to_define");\r
796   patterns.appendChild(delta);\r
797   QDomElement cons = doc.createElement("consumption");\r
798   foreach(AbstractInterface* iface, lstIface) {\r
799     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getPurpose() == AbstractInterface::Control)) {\r
800       QDomElement input = doc.createElement("input");\r
801       input.setAttribute("name",iface->getName());\r
802       input.setAttribute("pattern","to_define");\r
803       cons.appendChild(input);\r
804     }\r
805   }\r
806   patterns.appendChild(cons);\r
807   QDomElement prod = doc.createElement("production");\r
808   prod.setAttribute("counter","to_define");\r
809   foreach(AbstractInterface* iface, lstIface) {\r
810     if ((iface->getDirection() == AbstractInterface::Output) && (iface->getPurpose() == AbstractInterface::Control)) {\r
811       QDomElement output = doc.createElement("output");\r
812       output.setAttribute("name",iface->getName());\r
813       output.setAttribute("pattern","to_define");\r
814       prod.appendChild(output);\r
815     }\r
816   }\r
817   patterns.appendChild(prod);\r
818 }\r
819 \r
820 void VHDLConverter::replaceSignalNames(QString& line) {\r
821   foreach(AbstractInterface* iface, lstIface) {\r
822     QString pattern = iface->getName() + "([^a-zA-Z0-9_])";\r
823     QString repl = "@{"+iface->getName()+"}\\1";\r
824     QRegularExpression rxPort(pattern,QRegularExpression::CaseInsensitiveOption);\r
825     line.replace(rxPort,repl);\r
826   }\r
827 \r
828 }\r
829 \r
830 void VHDLConverter::updateArchitecture() {\r
831   QRegularExpression rxLT("<=",QRegularExpression::CaseInsensitiveOption);\r
832   QRegularExpression rxGT("=>",QRegularExpression::CaseInsensitiveOption);\r
833   for(int i=0;i<archLines.size();i++) {\r
834     QString line = archLines.at(i);\r
835     replaceSignalNames(line);\r
836     //line.replace(rxLT,"&lt;=");\r
837     //line.replace(rxGT,"=&gt;");\r
838     archLines.replace(i,line);\r
839     cout << qPrintable(line) << endl;\r
840   }\r
841 }\r
842 \r
843 // This function gets the informations in the table and the descriptions, and creates a XML file with this content\r
844 void VHDLConverter::generateXml() {\r
845 \r
846 \r
847   updateArchitecture();\r
848 \r
849   // creating reference xml\r
850   QDomDocument docRef(entityName);\r
851   generateRefXml(docRef);\r
852 \r
853   // creating implementation xml\r
854   QDomDocument docImpl(entityName);\r
855   generateImplXml(docImpl);\r
856 \r
857   QString dir = QFileDialog::getExistingDirectory(this,tr("Save file in"),".",QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);\r
858 \r
859   QString fileName = dir + "/"+ entityName + ".xml";\r
860 \r
861   QFile fileRef(fileName);\r
862   if(!fileRef.open(QIODevice::WriteOnly | QIODevice::Text)) {\r
863     cerr << "Cannot save in " << qPrintable(fileName) << endl;\r
864     return;\r
865   }\r
866   QTextStream tsRef(&fileRef);\r
867   docRef.save(tsRef,QDomNode::EncodingFromTextStream);\r
868   fileRef.close();\r
869 \r
870   fileName = dir + "/"+ entityName + "_impl.xml";\r
871   QFile fileImpl(fileName);\r
872   if(!fileImpl.open(QIODevice::WriteOnly | QIODevice::Text)) {\r
873     cerr << "Cannot save in " << qPrintable(fileName) << endl;\r
874     return;\r
875   }\r
876   QTextStream tsImpl(&fileImpl);\r
877   docImpl.save(tsImpl,QDomNode::EncodingFromTextStream);\r
878   fileImpl.close();\r
879 \r
880 }\r