1 #include "VHDLConverter.h"
\r
6 VHDLConverter::VHDLConverter(QWidget *parent) : QWidget(parent) {
\r
8 QLabel *labelAppli, *lblBrief, *lblDesc, *lblName, *lblPort, *lblGen;
\r
10 loadBut = new QPushButton("load VHDL");
\r
11 genBut = new QPushButton("generate XML");
\r
12 QHBoxLayout *widgetLayout = new QHBoxLayout;
\r
13 QVBoxLayout *left = new QVBoxLayout;
\r
14 QVBoxLayout *right = new QVBoxLayout;
\r
16 scrollDataPort = new QScrollArea;
\r
17 scrollDataPort->setWidgetResizable(true);
\r
18 twDataPort = new QTableWidget(this);
\r
19 scrollDataPort->setWidget(twDataPort);
\r
20 scrollGenerics = new QScrollArea;
\r
21 scrollGenerics->setWidgetResizable(true);
\r
22 twGenerics = new QTableWidget(this);
\r
23 scrollGenerics->setWidget(twGenerics);
\r
24 teName = new QTextEdit;
\r
25 teBrief = new QTextEdit;
\r
26 teDesc = new QTextEdit;
\r
27 lblName = new QLabel("Block name :");
\r
28 lblBrief = new QLabel("Enter a brief description : ");
\r
29 lblDesc = new QLabel("Enter a detailled description : ");
\r
30 lblPort = new QLabel("Ports :");
\r
31 lblGen = new QLabel("Generics :");
\r
33 connect(loadBut, SIGNAL(clicked()),this, SLOT(loadVHDLFile()));
\r
34 connect(genBut, SIGNAL(clicked()), this, SLOT(generateXml()));
\r
36 left->addWidget(loadBut);
\r
37 left->addWidget(lblPort);
\r
38 left->addWidget(scrollDataPort);
\r
39 left->addWidget(lblGen);
\r
40 left->addWidget(scrollGenerics);
\r
42 right->addWidget(lblName);
\r
43 right->addWidget(teName);
\r
44 right->addWidget(lblBrief);
\r
45 right->addWidget(teBrief);
\r
46 right->addWidget(lblDesc);
\r
47 right->addWidget(teDesc);
\r
48 right->addWidget(genBut);
\r
50 widgetLayout->addLayout(left);
\r
51 widgetLayout->addLayout(right);
\r
52 setLayout(widgetLayout);
\r
56 VHDLConverter::~VHDLConverter() {
\r
60 QString VHDLConverter::skipBlankAndComments(QTextStream &in) {
\r
64 // skipping blank/comment lines
\r
65 while ( (line.isEmpty()) || ((line.at(0) == '-') && (line.at(1) == '-')) ) {
\r
69 line = in.readLine();
\r
70 if (!line.isEmpty()) line = line.simplified();
\r
72 line.remove(QRegularExpression("--.*$"));
\r
76 QString VHDLConverter::readLibraries(QTextStream &in) throw(Exception) {
\r
78 QRegularExpression rxLib("^library[\\s\\t]*(.+);$",QRegularExpression::CaseInsensitiveOption);
\r
79 QRegularExpression rxPack("^use[\\s\\t]*([^.]+)[.](.+);$",QRegularExpression::CaseInsensitiveOption);
\r
82 line = skipBlankAndComments(in);
\r
84 throw(Exception(VHDLFILE_CORRUPTED));
\r
87 while (! line.contains("entity",Qt::CaseInsensitive)) {
\r
89 QRegularExpressionMatch matchLib = rxLib.match(line);
\r
90 QRegularExpressionMatch matchPack = rxPack.match(line);
\r
92 if (matchLib.hasMatch()) {
\r
94 QString libName = matchLib.captured(1);
\r
95 libName = libName.toLower();
\r
97 cout << "matching library: " << qPrintable(libName) << endl;
\r
99 if (!packages.contains(libName)) {
\r
100 packages.insert(libName,new QList<QString>());
\r
103 else if (matchPack.hasMatch()) {
\r
104 cout << "matching packages" << endl;
\r
106 QString libName = matchPack.captured(1);
\r
107 QString packName = matchPack.captured(2);
\r
109 libName = libName.toLower();
\r
110 packName = packName.toLower();
\r
112 if (libName == "work") {
\r
113 if (!packages.contains("work")) {
\r
114 packages.insert("work",new QList<QString>());
\r
117 else if (libName == "std") {
\r
118 if (!packages.contains("std")) {
\r
119 packages.insert("std",new QList<QString>());
\r
122 else if (!packages.contains(libName)) throw(Exception(VHDLFILE_CORRUPTED));
\r
124 QList<QString>* lstPack = packages.value(libName);
\r
125 QString s = libName + "." + packName;
\r
126 lstPack->append(s);
\r
127 cout << qPrintable(s) << endl;
\r
131 line = skipBlankAndComments(in);
\r
133 throw(Exception(VHDLFILE_CORRUPTED));
\r
135 cout << "read line = " << qPrintable(line) << endl;
\r
141 QString VHDLConverter::readEntity(QTextStream &in) throw(Exception) {
\r
143 QRegularExpression rxGen("^generic[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);
\r
144 QRegularExpression rxPorts("^port[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);
\r
148 line = skipBlankAndComments(in);
\r
150 throw(Exception(VHDLFILE_CORRUPTED));
\r
153 while (! line.contains("architecture",Qt::CaseInsensitive)) {
\r
155 QRegularExpressionMatch matchGen = rxGen.match(line);
\r
156 QRegularExpressionMatch matchPorts = rxPorts.match(line);
\r
158 if (matchGen.hasMatch()) {
\r
159 cout << "matching generics" << endl;
\r
160 if (matchGen.captured(1).length() > 0) {
\r
161 cerr << "Please, modify VHDL source so that the generic list does not begin at the same line as generic (" << endl;
\r
162 throw(Exception(VHDLFILE_CORRUPTED));
\r
166 else if (matchPorts.hasMatch()) {
\r
167 cout << "matching ports" << endl;
\r
168 if (matchPorts.captured(1).length() > 0) {
\r
169 cerr << "Please, modify VHDL source so that the port list does not begin at the same line as port (" << endl;
\r
170 throw(Exception(VHDLFILE_CORRUPTED));
\r
175 line = skipBlankAndComments(in);
\r
177 throw(Exception(VHDLFILE_CORRUPTED));
\r
179 cout << "read line = " << qPrintable(line) << endl;
\r
185 void VHDLConverter::readGenerics(QTextStream &in) throw(Exception) {
\r
187 QRegularExpression rxGen("^([^:]+):([^:]+)(:=)?([^;]*);?$",QRegularExpression::CaseInsensitiveOption);
\r
191 line = skipBlankAndComments(in);
\r
193 throw(Exception(VHDLFILE_CORRUPTED));
\r
195 line = line.remove(' ');
\r
197 while (! line.contains(QRegExp("\\);"))) {
\r
199 QRegularExpressionMatch matchGen = rxGen.match(line);
\r
201 if (matchGen.hasMatch()) {
\r
202 cout << "matching generic value" << endl;
\r
203 QString genName = matchGen.captured(1);
\r
204 QString genType = matchGen.captured(2);
\r
205 QString genValue = matchGen.captured(4);
\r
206 cout << qPrintable(genName) << " " << qPrintable(genType) << " " << qPrintable(genValue) << endl;
\r
209 line = skipBlankAndComments(in);
\r
211 throw(Exception(VHDLFILE_CORRUPTED));
\r
213 line = line.remove(' ');
\r
214 cout << "read line = " << qPrintable(line) << endl;
\r
218 void VHDLConverter::readPorts(QTextStream &in) throw(Exception) {
\r
220 QRegularExpression rxPort("^([^:]+):(in|out|inout)([a-zA-Z0-9_]+)(\\([^:)]*\\))?(:=)?([^;]*);?$",QRegularExpression::CaseInsensitiveOption);
\r
224 line = skipBlankAndComments(in);
\r
226 throw(Exception(VHDLFILE_CORRUPTED));
\r
228 line = line.remove(' ');
\r
230 while (! line.contains(QRegExp("^\\);$"))) {
\r
232 QRegularExpressionMatch matchPort = rxPort.match(line);
\r
234 if (matchPort.hasMatch()) {
\r
235 cout << "matching port value" << endl;
\r
236 QString portName = matchPort.captured(1);
\r
237 QString portDir = matchPort.captured(2);
\r
238 QString portType = matchPort.captured(3);
\r
239 QString portSize = matchPort.captured(4);
\r
240 QString portValue = matchPort.captured(6);
\r
241 cout << qPrintable(portName) << " " << qPrintable(portDir) << " " << qPrintable(portType) << " " << qPrintable(portSize) << " " << qPrintable(portValue) << endl;
\r
244 line = skipBlankAndComments(in);
\r
246 throw(Exception(VHDLFILE_CORRUPTED));
\r
248 line = line.remove(' ');
\r
249 cout << "read line = " << qPrintable(line) << endl;
\r
254 void VHDLConverter::readArchitecture(QTextStream &in) throw(Exception) {
\r
258 // This function opens a VHDL file and get the informations about the entity :
\r
259 // First the generics, then the signals.
\r
260 // You can edit the descriptions in the right, one for the brief description, the other for the detailled.
\r
261 void VHDLConverter::loadVHDLFile() {
\r
263 QString line, portName, portType, portId, genName, genType, genValue;
\r
264 QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList;
\r
266 twDataPort->setColumnCount(3);
\r
267 twDataPort->setRowCount(cpt);
\r
268 twGenerics->setColumnCount(3);
\r
269 twGenerics->setRowCount(cpt);
\r
270 portNameList = new QStringList;
\r
271 portTypeList = new QStringList;
\r
272 portIdList = new QStringList;
\r
273 genNameList = new QStringList;
\r
274 genTypeList = new QStringList;
\r
275 genValueList = new QStringList;
\r
278 fileName = QFileDialog::getOpenFileName(this,
\r
279 tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)"));
\r
280 QFile file(fileName);
\r
282 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
\r
284 QTextStream ts(&file);
\r
286 QString entityLine = "";
\r
288 entityLine = readLibraries(ts);
\r
290 catch(Exception e) {
\r
291 cerr << "VHDL seems to be malformed" << endl;
\r
295 QRegularExpression rxEnt("^entity[\\s\\t]+(.+)[\\s\\t]+is$",QRegularExpression::CaseInsensitiveOption);
\r
296 QRegularExpressionMatch matchEnt = rxEnt.match(entityLine);
\r
297 if (!matchEnt.hasMatch()) {
\r
298 cerr << "VHDL seems to be malformed" << endl;
\r
301 entityName = matchEnt.captured(1);
\r
302 cout << "foudn entity " << qPrintable(entityName) << endl;
\r
304 QString archLine = "";
\r
306 archLine = readEntity(ts);
\r
308 catch(Exception e) {
\r
309 cerr << "VHDL seems to be malformed" << endl;
\r
315 while (!ts.atEnd())
\r
317 line = ts.readLine();
\r
318 if(rxComment->indexIn(line) != -1) {
\r
319 line = rxComment->cap(1);
\r
322 if(rxEnt->indexIn(line)!= -1) {
\r
324 entName = rxEnt->cap(1);
\r
325 teName->setText(entName);
\r
326 QSize size = teName->document()->size().toSize();
\r
327 teName->setMaximumSize(size);
\r
329 while(rxEnd->indexIn(line) == -1) {
\r
330 line = ts.readLine();
\r
331 if(rxComment->indexIn(line) != -1) {
\r
332 line = rxComment->cap(1);
\r
334 if(rxComma->indexIn(line) != -1) {
\r
335 line = rxComma->cap(1);
\r
337 if(rxGeneric->indexIn(line) != -1) {
\r
338 while(rxEndGen->indexIn(line) == -1) {
\r
339 line = ts.readLine();
\r
340 if(rxComment->indexIn(line) != -1) {
\r
341 line = rxComment->cap(1);
\r
343 if(rxComma->indexIn(line) != -1) {
\r
344 line = rxComma->cap(1);
\r
346 if(rxGen->indexIn(line) != -1) {
\r
347 genName = rxGen->cap(1).simplified();
\r
348 genType = rxGen->cap(2).simplified();
\r
349 genValue = rxGen->cap(3).simplified();
\r
351 genNameList->append(genName);
\r
352 genTypeList->append(genType);
\r
353 genValueList->append(genValue);
\r
357 if(rxPort->indexIn(line) != -1) {
\r
358 if(rxComment->indexIn(line) != -1) {
\r
359 line = rxComment->cap(1);
\r
361 if(rxComma->indexIn(line) != -1) {
\r
362 line = rxComma->cap(1);
\r
364 portName = rxPort->cap(1).simplified();
\r
365 portId = rxPort->cap(2).simplified();
\r
366 portType = rxPort->cap(3).simplified();
\r
367 portNameList->append(portName);
\r
368 portIdList->append(portId);
\r
369 portTypeList->append(portType);
\r
376 twGenerics->setRowCount(genNameList->size());
\r
377 for(int i = 0; i < genNameList->size(); i++) {
\r
378 twGenerics->setItem(i, 0, new QTableWidgetItem(genNameList->at(i)));
\r
379 twGenerics->setItem(i, 1, new QTableWidgetItem(genTypeList->at(i)));
\r
380 twGenerics->setItem(i, 2, new QTableWidgetItem(genValueList->at(i)));
\r
382 twDataPort->setRowCount(portNameList->size());
\r
383 for(int i = 0; i < portNameList->size(); i++) {
\r
384 twDataPort->setItem(i, 0, new QTableWidgetItem(portIdList->at(i)));
\r
385 twDataPort->setItem(i, 1, new QTableWidgetItem(portNameList->at(i)));
\r
386 twDataPort->setItem(i, 2, new QTableWidgetItem(portTypeList->at(i)));
\r
390 scrollDataPort->setWidget(twDataPort);
\r
394 // This function gets the informations in the table and the descriptions, and creates a XML file with this content
\r
395 void VHDLConverter::generateXml() {
\r
397 QString portName, portType, portId, genName, genType, genValue;
\r
398 QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList;
\r
400 brief = teBrief->toPlainText();
\r
401 desc = teDesc->toPlainText();
\r
402 entName = teName->toPlainText();
\r
404 portNameList = new QStringList;
\r
405 portTypeList = new QStringList;
\r
406 portIdList = new QStringList;
\r
407 genNameList = new QStringList;
\r
408 genTypeList = new QStringList;
\r
409 genValueList = new QStringList;
\r
410 for(int i = 0; i < twGenerics->rowCount(); i++) {
\r
411 genNameList->append(twGenerics->item(i,0)->text());
\r
412 genTypeList->append(twGenerics->item(i,1)->text());
\r
413 genValueList->append(twGenerics->item(i,2)->text());
\r
416 for(int i = 0; i < twDataPort->rowCount(); i++) {
\r
417 portIdList->append(twDataPort->item(i,0)->text());
\r
418 portNameList->append(twDataPort->item(i,1)->text());
\r
419 portTypeList->append(twDataPort->item(i,2)->text());
\r
422 QDomDocument doc (entName);
\r
423 QDomElement block = doc.createElement("block");
\r
424 block.setAttribute("name",entName);
\r
425 block.setAttribute("version", "0.1");
\r
426 doc.appendChild(block);
\r
428 QDomElement comments = doc.createElement("comments");
\r
429 QDomElement category = doc.createElement("caterory");
\r
430 category.setAttribute("ids","");
\r
431 comments.appendChild(category);
\r
433 QDomElement eBrief = doc.createElement("brief");
\r
434 if(!brief.isEmpty()) {
\r
435 QDomText txtBrief = doc.createTextNode(brief);
\r
436 eBrief.appendChild(txtBrief);
\r
437 comments.appendChild(eBrief);
\r
439 QDomElement eDesc = doc.createElement("description");
\r
440 if(!desc.isEmpty()) {
\r
441 QDomText txtDesc = doc.createTextNode(desc);
\r
442 eDesc.appendChild(txtDesc);
\r
443 comments.appendChild(eDesc);
\r
445 block.appendChild(comments);
\r
447 QDomElement parameters = doc.createElement("parameters");
\r
448 QDomElement interfaces = doc.createElement("interfaces");
\r
449 QDomElement inputs = doc.createElement("inputs");
\r
450 QDomElement outputs = doc.createElement("outputs");
\r
451 QDomElement bidirs = doc.createElement("bidirs");
\r
452 block.appendChild(parameters);
\r
453 block.appendChild(interfaces);
\r
454 interfaces.appendChild(inputs);
\r
455 interfaces.appendChild(outputs);
\r
456 interfaces.appendChild(bidirs);
\r
458 for(int i = 0; i < twGenerics->rowCount(); i++) {
\r
459 genName = genNameList->at(i);
\r
460 genType = genTypeList->at(i);
\r
461 genValue = genValueList->at(i);
\r
462 QDomElement parameter = doc.createElement("parameter");
\r
463 parameter.setAttribute("name",genName);
\r
464 parameter.setAttribute("type",genType);
\r
465 parameter.setAttribute("value",genValue);
\r
466 parameter.setAttribute("context","generic");
\r
467 parameters.appendChild(parameter);
\r
470 for(int i = 0; i < portIdList->size(); i++) {
\r
471 portId = portIdList->at(i);
\r
472 portName = portNameList->at(i);
\r
473 portType = portTypeList->at(i);
\r
474 if(rxWidth->indexIn(portType) != -1) {
\r
475 x = rxWidth->cap(1).toInt();
\r
476 y = rxWidth->cap(3).toInt();
\r
485 if(portId.compare("in", CaseInsensitive) == 0) {
\r
486 QDomElement input = doc.createElement("input");
\r
487 input.setAttribute("name",portName);
\r
488 input.setAttribute("width", width);
\r
489 inputs.appendChild(input);
\r
491 else if(portId.compare("out", CaseInsensitive) == 0) {
\r
492 QDomElement output = doc.createElement("output");
\r
493 output.setAttribute("name",portName);
\r
494 output.setAttribute("width", width);
\r
495 outputs.appendChild(output);
\r
497 else if(portId.compare("inout", CaseInsensitive) == 0) {
\r
498 QDomElement bidir = doc.createElement("bidir");
\r
499 bidir.setAttribute("name",portName);
\r
500 bidir.setAttribute("width", width);
\r
501 bidirs.appendChild(bidir);
\r
505 fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
\r
506 "C:", tr("Files (*.xml)"));
\r
507 QFile file(fileName);
\r
508 if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
\r
510 QTextStream ts(&file);
\r
511 doc.save(ts,QDomNode::EncodingFromTextStream);
\r
514 QLabel *popup = new QLabel("Votre fichier XML est rempli");
\r