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

Private GIT Repository
started top group gen, added project subdirs
[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 endLine = "end "+archName;\r
363 \r
364   while (!line.startsWith(endLine)) {\r
365     line = in.readLine();\r
366     if (!line.isEmpty()) line = line.simplified();\r
367     archLines.append(line);\r
368   }\r
369   \r
370 }\r
371 \r
372 // This function opens a VHDL file and get the informations about the entity :\r
373 // First the generics, then the signals.\r
374 // You can edit the descriptions in the right, one for the brief description, the other for the detailled.\r
375 void VHDLConverter::loadVHDLFile() {\r
376 \r
377   QString fileName = QFileDialog::getOpenFileName(this,\r
378                                                   tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)"));\r
379   QFile file(fileName);\r
380 \r
381   if(!file.open(QIODevice::ReadOnly | QIODevice::Text))\r
382     return;\r
383   QTextStream ts(&file);\r
384 \r
385   block = new ReferenceBlock(fileName);\r
386 \r
387   QString entityLine = "";\r
388   try {\r
389     entityLine = readLibraries(ts);\r
390   }\r
391   catch(Exception e) {\r
392     cerr << "VHDL seems to be malformed" << endl;\r
393     return;\r
394   }\r
395 \r
396   QRegularExpression rxEnt("^entity (.+) is$",QRegularExpression::CaseInsensitiveOption);\r
397   QRegularExpressionMatch matchEnt = rxEnt.match(entityLine);\r
398   if (!matchEnt.hasMatch()) {\r
399     cerr << "VHDL seems to be malformed" << endl;\r
400     return;\r
401   }\r
402   entityName = matchEnt.captured(1);\r
403   cout << "found entity " << qPrintable(entityName) << endl;\r
404 \r
405   QString archLine = "";\r
406   try {\r
407     archLine = readEntity(ts);\r
408   }\r
409   catch(Exception e) {\r
410     cerr << "VHDL seems to be malformed" << endl;\r
411     return;\r
412   }\r
413 \r
414   QRegularExpression rxArch("^architecture (.+) of (.+) is$",QRegularExpression::CaseInsensitiveOption);\r
415   QRegularExpressionMatch matchArch = rxArch.match(archLine);\r
416   if (!matchArch.hasMatch()) {\r
417     cerr << "VHDL seems to be malformed" << endl;\r
418     return;\r
419   }\r
420   archName = matchArch.captured(1);\r
421   cout << "found arch " << qPrintable(archName) << " for entity " << qPrintable(matchArch.captured(2)) << endl;\r
422 \r
423   try {\r
424     readArchitecture(ts);\r
425   }\r
426   catch(Exception e) {\r
427     cerr << "VHDL seems to be malformed" << endl;\r
428     return;\r
429   }\r
430   file.close();\r
431 \r
432 \r
433   QList<BlockParameter*> lstGenerics = block->getGenericParameters();\r
434   twGenerics->setRowCount(lstGenerics.size());\r
435   int i = 0;\r
436   foreach(BlockParameter* param, lstGenerics) {\r
437     twGenerics->setItem(i, 0, new QTableWidgetItem(param->getName()));\r
438     twGenerics->setItem(i, 1, new QTableWidgetItem(param->getTypeString()));\r
439     twGenerics->setItem(i, 2, new QTableWidgetItem(param->getValue().toString()));\r
440     i++;\r
441   }\r
442 \r
443   lstIface = block->getInputs();\r
444   lstIface.append(block->getOutputs());\r
445   lstIface.append(block->getBidirs());\r
446 \r
447   twPorts->setRowCount(lstIface.size());\r
448   purposeDelegate = new IfacePurposeDelegate();\r
449   twPorts->setItemDelegateForColumn(3,purposeDelegate);\r
450 \r
451   i=0;\r
452   foreach(AbstractInterface* iface, lstIface) {\r
453     twPorts->setItem(i, 0, new QTableWidgetItem(iface->getName()));\r
454     twPorts->setItem(i, 1, new QTableWidgetItem(iface->getDirectionString()));\r
455     QString widthStr="";\r
456     if (iface->getType() == AbstractInterface::Boolean) {\r
457       widthStr = "std_logic";\r
458     }\r
459     else {\r
460       widthStr = "std_logic_vector(";\r
461       if (iface->getEndianess() == AbstractInterface::LittleEndian) {\r
462         widthStr += iface->getWidth();\r
463         widthStr += " downto 0)";\r
464       }\r
465       else {\r
466         widthStr += "0 to ";\r
467         widthStr += iface->getWidth();\r
468         widthStr += ")";\r
469       }\r
470     }\r
471     twPorts->setItem(i, 2, new QTableWidgetItem(widthStr));\r
472 \r
473     QTableWidgetItem* item = new QTableWidgetItem(iface->getPurposeString());\r
474     twPorts->setItem(i, 3, item);\r
475 \r
476     // trying to find wihch other iface this one controls\r
477     QString assoInter = "N/A";\r
478     if (iface->getPurpose() == AbstractInterface::Control) {\r
479       QString name = iface->getName();\r
480       name.remove(name.size()-4,4); // remove _enb at the end\r
481       foreach(AbstractInterface* inter, lstIface) {\r
482         if ((inter != iface) && (inter->getName().contains(name))) {\r
483           assoInter = inter->getName();\r
484           iface->setAssociatedIface(inter);\r
485         }\r
486       }\r
487     }\r
488     QTableWidgetItem* itemAsso = new QTableWidgetItem(assoInter);\r
489     if (iface->getPurpose() != AbstractInterface::Control) {\r
490       itemAsso->setFlags(Qt::NoItemFlags);\r
491     }\r
492     twPorts->setItem(i, 4, itemAsso);\r
493 \r
494     i++;\r
495   }\r
496 \r
497   connect(twPorts,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(searchAssociatedPort(QTableWidgetItem*)));\r
498 \r
499   //file.close();\r
500 \r
501   //scrollPorts->setWidget(twPorts);\r
502   editEntityName->setText(entityName);\r
503   editLongName->setText(entityName);\r
504   return;\r
505 }\r
506 \r
507 void VHDLConverter::searchAssociatedPort(QTableWidgetItem *item) {\r
508 \r
509   bool ok;\r
510   int col = item->column();\r
511   int row = item->row();\r
512 \r
513   // searching for the real interface object linked to the item\r
514   AbstractInterface* iface = NULL;\r
515   QString ifaceName = twPorts->item(row,0)->text();\r
516   foreach(AbstractInterface* inter,lstIface) {\r
517     if (inter->getName() == ifaceName) {\r
518       iface = inter;\r
519       break;\r
520     }\r
521   }\r
522 \r
523   if (col == 3) {\r
524 \r
525     QString assoInter = "N/A";\r
526     iface->setAssociatedIface(NULL);\r
527 \r
528     cout << qPrintable(item->text()) << endl;\r
529 \r
530     if (item->text() == "data") {\r
531       iface->setPurpose(AbstractInterface::Data);\r
532     }\r
533     else if (item->text() == "control") {\r
534       iface->setPurpose(AbstractInterface::Control);\r
535     }\r
536     else if (item->text() == "clock") {\r
537       iface->setPurpose(AbstractInterface::Clock);\r
538     }\r
539     else if (item->text() == "reset") {\r
540       iface->setPurpose(AbstractInterface::Reset);\r
541     }\r
542     else if (item->text() == "wishbone") {\r
543       iface->setPurpose(AbstractInterface::Wishbone);\r
544     }\r
545 \r
546     if (item->text() == "control") {\r
547 \r
548       QString name = twPorts->item(row,0)->text();\r
549       name.remove(name.size()-4,4); // remove _enb at the end\r
550       int i=0;\r
551       foreach(AbstractInterface* inter, lstIface) {\r
552         if ((i != row) && (inter->getName().contains(name))) {\r
553           assoInter = inter->getName();\r
554           iface->setAssociatedIface(inter);\r
555         }\r
556         i++;\r
557       }\r
558     }\r
559 \r
560     QTableWidgetItem* itemAsso = twPorts->item(row,4);\r
561     itemAsso->setText(assoInter);\r
562 \r
563     if (item->text() == "control") {\r
564       itemAsso->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable);\r
565     }\r
566     else {\r
567       itemAsso->setFlags(Qt::NoItemFlags);\r
568     }\r
569   }\r
570   else if (col == 4) {\r
571 \r
572     QString nameAsso = item->text();\r
573     if (nameAsso == "N/A") return;\r
574 \r
575     bool found = false;\r
576 \r
577     int i=0;\r
578     foreach(AbstractInterface* inter, lstIface) {\r
579       if ((i != row) && (inter->getName().contains(nameAsso))) {\r
580         found = true;\r
581         iface->setAssociatedIface(inter);\r
582       }\r
583     }\r
584     if (!found) {\r
585       QTableWidgetItem* itemAsso = twPorts->item(row,4);\r
586       itemAsso->setText("N/A");\r
587     }\r
588   }\r
589 }\r
590 \r
591 void VHDLConverter::generateRefXml(QDomDocument& doc) {\r
592 \r
593   QDomElement eBlock = doc.createElement("block");\r
594   eBlock.setAttribute("version", "0.1");\r
595   doc.appendChild(eBlock);\r
596 \r
597   // creating infos\r
598   QDomElement infos = doc.createElement("informations");\r
599   eBlock.appendChild(infos);\r
600 \r
601   QDomElement eName = doc.createElement("name");\r
602   QDomText tName = doc.createTextNode(editLongName->text());\r
603   eName.appendChild(tName);\r
604   infos.appendChild(eName);\r
605 \r
606   QDomElement category = doc.createElement("category");\r
607   category.setAttribute("ids","");\r
608   infos.appendChild(category);\r
609 \r
610   QDomElement eDesc = doc.createElement("description");\r
611   QString brief = teBrief->toPlainText();\r
612   QString detailed = teDesc->toPlainText();\r
613   QDomElement eBrief = doc.createElement("brief");\r
614   if(!brief.isEmpty()) {\r
615     QDomText txtBrief = doc.createTextNode(brief);\r
616     eBrief.appendChild(txtBrief);\r
617     eDesc.appendChild(eBrief);\r
618   }\r
619   QDomElement eDetailed = doc.createElement("detailed");\r
620   if(!detailed.isEmpty()) {\r
621     QDomText txtDetailed = doc.createTextNode(detailed);\r
622     eDetailed.appendChild(txtDetailed);\r
623     eDesc.appendChild(eDetailed);\r
624   }\r
625   infos.appendChild(eDesc);\r
626 \r
627 \r
628 \r
629   QDomElement parameters = doc.createElement("parameters");\r
630   eBlock.appendChild(parameters);\r
631 \r
632   QList<BlockParameter*> lstGenerics = block->getGenericParameters();\r
633   foreach(BlockParameter* param, lstGenerics) {\r
634     QDomElement parameter = doc.createElement("parameter");\r
635     parameter.setAttribute("name",param->getName());\r
636     parameter.setAttribute("type",param->getTypeString());\r
637     parameter.setAttribute("value",param->getValue().toString());\r
638     parameter.setAttribute("context","generic");\r
639     parameters.appendChild(parameter);\r
640   }\r
641 \r
642   QDomElement interfaces = doc.createElement("interfaces");\r
643   eBlock.appendChild(interfaces);\r
644 \r
645   if (block->getInputs().size() > 0) {\r
646     QDomElement inputs = doc.createElement("inputs");\r
647     interfaces.appendChild(inputs);\r
648     foreach(AbstractInterface* iface, block->getInputs()) {\r
649 \r
650       if (iface->getPurpose() != AbstractInterface::Control) {\r
651         QDomElement input = doc.createElement("input");\r
652         input.setAttribute("name",iface->getName());\r
653         input.setAttribute("type",iface->getTypeString());\r
654         input.setAttribute("width",iface->getWidth());\r
655         input.setAttribute("multiplicity","1");\r
656         input.setAttribute("purpose",iface->getPurposeString());\r
657         input.setAttribute("endian",iface->getEndianessString());\r
658         inputs.appendChild(input);\r
659       }\r
660       else {\r
661         QDomElement ctl = doc.createElement("control");\r
662         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
663         inputs.appendChild(ctl);\r
664       }\r
665     }\r
666   }\r
667 \r
668   if (block->getOutputs().size() > 0) {\r
669     QDomElement outputs = doc.createElement("outputs");\r
670     interfaces.appendChild(outputs);\r
671     foreach(AbstractInterface* iface, block->getOutputs()) {\r
672       if (iface->getPurpose() != AbstractInterface::Control) {\r
673         QDomElement output = doc.createElement("output");\r
674         output.setAttribute("name",iface->getName());\r
675         output.setAttribute("type",iface->getTypeString());\r
676         output.setAttribute("width",iface->getWidth());\r
677         output.setAttribute("multiplicity","1");\r
678         output.setAttribute("purpose",iface->getPurposeString());\r
679         output.setAttribute("endian",iface->getEndianessString());\r
680         outputs.appendChild(output);\r
681       }\r
682       else {\r
683         QDomElement ctl = doc.createElement("control");\r
684         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
685         outputs.appendChild(ctl);\r
686       }\r
687     }\r
688   }\r
689 \r
690   if (block->getBidirs().size() > 0) {\r
691     QDomElement bidirs = doc.createElement("bidirs");\r
692     interfaces.appendChild(bidirs);\r
693     foreach(AbstractInterface* iface, block->getBidirs()) {\r
694       if (iface->getPurpose() != AbstractInterface::Control) {\r
695         QDomElement bidir = doc.createElement("bidir");\r
696         bidir.setAttribute("name",iface->getName());\r
697         bidir.setAttribute("type",iface->getTypeString());\r
698         bidir.setAttribute("width",iface->getWidth());\r
699         bidir.setAttribute("multiplicity","1");\r
700         bidir.setAttribute("purpose",iface->getPurposeString());\r
701         bidir.setAttribute("endian",iface->getEndianessString());\r
702         bidirs.appendChild(bidir);\r
703       }\r
704       else {\r
705         QDomElement ctl = doc.createElement("control");\r
706         ctl.setAttribute("iface",iface->getAssociatedIface()->getName());\r
707         bidirs.appendChild(ctl);\r
708       }\r
709     }\r
710   }\r
711 }\r
712 \r
713 void VHDLConverter::generateImplXml(QDomDocument& doc) {\r
714 \r
715   QRegularExpression rxPack("^([^.]+)[.](.+)$",QRegularExpression::CaseInsensitiveOption);\r
716 \r
717   QDomElement eBlock = doc.createElement("block_impl");\r
718   eBlock.setAttribute("ref_name", entityName+".xml");\r
719   eBlock.setAttribute("ref_md5", "");\r
720   doc.appendChild(eBlock);\r
721 \r
722   // creating infos\r
723   QDomElement comments = doc.createElement("comments");\r
724   eBlock.appendChild(comments);\r
725 \r
726   QDomElement author = doc.createElement("author");\r
727   author.setAttribute("firstname","");\r
728   author.setAttribute("lastname","");\r
729   author.setAttribute("mail","");\r
730   comments.appendChild(author);\r
731 \r
732   QDomElement date = doc.createElement("date");\r
733   date.setAttribute("creation","");\r
734   comments.appendChild(date);\r
735 \r
736   QString brief = teBrief->toPlainText();\r
737   QString detailed = teDesc->toPlainText();\r
738   QDomElement eDesc = doc.createElement("description");\r
739   if(!brief.isEmpty()) {\r
740     QDomText txtBrief = doc.createTextNode(brief);\r
741     eDesc.appendChild(txtBrief);\r
742     comments.appendChild(eDesc);\r
743   }\r
744   QDomElement eNotes = doc.createElement("notes");\r
745   if(!detailed.isEmpty()) {\r
746     QDomText txtDetailed = doc.createTextNode(detailed);\r
747     eNotes.appendChild(txtDetailed);\r
748     comments.appendChild(eNotes);\r
749   }\r
750 \r
751   QDomElement libs = doc.createElement("libraries");\r
752   eBlock.appendChild(libs);\r
753 \r
754   QHashIterator<QString,QList<QString>* > it(packages);\r
755 \r
756   while (it.hasNext()) {\r
757     it.next();\r
758     QString libName = it.key();\r
759     cout << qPrintable(libName) << endl;\r
760     QList<QString>* packList = it.value();\r
761     QDomElement lib = doc.createElement("library");\r
762     lib.setAttribute("name", libName);\r
763     libs.appendChild(lib);\r
764 \r
765     foreach(QString packName, *packList) {\r
766       QDomElement pack = doc.createElement("package");\r
767       lib.appendChild(pack);\r
768       QRegularExpressionMatch matchPack = rxPack.match(packName);\r
769       if (matchPack.hasMatch()) {\r
770         QString name = matchPack.captured(1);\r
771         QString subName = matchPack.captured(2);\r
772         name = name.toLower();\r
773         subName = subName.toLower();\r
774         pack.setAttribute("name",name);\r
775         pack.setAttribute("use",subName);\r
776       }\r
777     }\r
778   }\r
779 \r
780   QDomElement archi = doc.createElement("architecture");\r
781   eBlock.appendChild(archi);\r
782   QDomText tName = doc.createTextNode("");\r
783   foreach(QString line, archLines) {\r
784     tName.appendData(line+"\n");\r
785   }\r
786   archi.appendChild(tName);\r
787 \r
788   QDomElement patterns = doc.createElement("patterns");\r
789   eBlock.appendChild(patterns);\r
790   QDomElement delta = doc.createElement("delta");\r
791   delta.setAttribute("value","to_define");\r
792   patterns.appendChild(delta);\r
793   QDomElement cons = doc.createElement("consumption");\r
794   foreach(AbstractInterface* iface, lstIface) {\r
795     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getPurpose() == AbstractInterface::Control)) {\r
796       QDomElement input = doc.createElement("input");\r
797       input.setAttribute("name",iface->getName());\r
798       input.setAttribute("pattern","to_define");\r
799       cons.appendChild(input);\r
800     }\r
801   }\r
802   patterns.appendChild(cons);\r
803   QDomElement prod = doc.createElement("production");\r
804   prod.setAttribute("counter","to_define");\r
805   foreach(AbstractInterface* iface, lstIface) {\r
806     if ((iface->getDirection() == AbstractInterface::Output) && (iface->getPurpose() == AbstractInterface::Control)) {\r
807       QDomElement output = doc.createElement("output");\r
808       output.setAttribute("name",iface->getName());\r
809       output.setAttribute("pattern","to_define");\r
810       prod.appendChild(output);\r
811     }\r
812   }\r
813   patterns.appendChild(prod);\r
814 }\r
815 \r
816 void VHDLConverter::replaceSignalNames(QString& line) {\r
817   foreach(AbstractInterface* iface, lstIface) {\r
818     QString pattern = iface->getName() + "([^a-zA-Z0-9_])";\r
819     QString repl = "@{"+iface->getName()+"}\\1";\r
820     QRegularExpression rxPort(pattern,QRegularExpression::CaseInsensitiveOption);\r
821     line.replace(rxPort,repl);\r
822   }\r
823 \r
824 }\r
825 \r
826 void VHDLConverter::updateArchitecture() {\r
827   QRegularExpression rxLT("<=",QRegularExpression::CaseInsensitiveOption);\r
828   QRegularExpression rxGT("=>",QRegularExpression::CaseInsensitiveOption);\r
829   for(int i=0;i<archLines.size();i++) {\r
830     QString line = archLines.at(i);\r
831     replaceSignalNames(line);\r
832     //line.replace(rxLT,"&lt;=");\r
833     //line.replace(rxGT,"=&gt;");\r
834     archLines.replace(i,line);\r
835     cout << qPrintable(line) << endl;\r
836   }\r
837 }\r
838 \r
839 // This function gets the informations in the table and the descriptions, and creates a XML file with this content\r
840 void VHDLConverter::generateXml() {\r
841 \r
842 \r
843   updateArchitecture();\r
844 \r
845   // creating reference xml\r
846   QDomDocument docRef(entityName);\r
847   generateRefXml(docRef);\r
848 \r
849   // creating implementation xml\r
850   QDomDocument docImpl(entityName);\r
851   generateImplXml(docImpl);\r
852 \r
853   QString dir = QFileDialog::getExistingDirectory(this,tr("Save file in"),".",QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);\r
854 \r
855   QString fileName = dir + "/"+ entityName + ".xml";\r
856 \r
857   QFile fileRef(fileName);\r
858   if(!fileRef.open(QIODevice::WriteOnly | QIODevice::Text)) {\r
859     cerr << "Cannot save in " << qPrintable(fileName) << endl;\r
860     return;\r
861   }\r
862   QTextStream tsRef(&fileRef);\r
863   docRef.save(tsRef,QDomNode::EncodingFromTextStream);\r
864   fileRef.close();\r
865 \r
866   fileName = dir + "/"+ entityName + "_impl.xml";\r
867   QFile fileImpl(fileName);\r
868   if(!fileImpl.open(QIODevice::WriteOnly | QIODevice::Text)) {\r
869     cerr << "Cannot save in " << qPrintable(fileName) << endl;\r
870     return;\r
871   }\r
872   QTextStream tsImpl(&fileImpl);\r
873   docImpl.save(tsImpl,QDomNode::EncodingFromTextStream);\r
874   fileImpl.close();\r
875 \r
876 }\r