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
10 VHDLConverter::VHDLConverter(QWidget *parent) : QWidget(parent) {
\r
12 QLabel *labelAppli, *lblBrief, *lblDesc, *lblEntName, *lblLongName, *lblPort, *lblGen;
\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
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
41 connect(loadBut, SIGNAL(clicked()),this, SLOT(loadVHDLFile()));
\r
42 connect(genBut, SIGNAL(clicked()), this, SLOT(generateXml()));
\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
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
60 widgetLayout->addLayout(left);
\r
61 widgetLayout->addLayout(right);
\r
62 setLayout(widgetLayout);
\r
66 VHDLConverter::~VHDLConverter() {
\r
70 QString VHDLConverter::skipBlankAndComments(QTextStream &in) {
\r
74 // skipping blank/comment lines
\r
75 while ( (line.isEmpty()) || ((line.at(0) == '-') && (line.at(1) == '-')) ) {
\r
79 line = in.readLine();
\r
80 if (!line.isEmpty()) line = line.simplified();
\r
82 line.remove(QRegularExpression("--.*$"));
\r
86 QString VHDLConverter::readLibraries(QTextStream &in) throw(Exception) {
\r
88 QRegularExpression rxLib("^library[\\s\\t]*(.+);$",QRegularExpression::CaseInsensitiveOption);
\r
89 QRegularExpression rxPack("^use[\\s\\t]*([^.]+)[.](.+);$",QRegularExpression::CaseInsensitiveOption);
\r
92 line = skipBlankAndComments(in);
\r
94 throw(Exception(VHDLFILE_CORRUPTED));
\r
97 while (! line.contains("entity",Qt::CaseInsensitive)) {
\r
99 QRegularExpressionMatch matchLib = rxLib.match(line);
\r
100 QRegularExpressionMatch matchPack = rxPack.match(line);
\r
102 if (matchLib.hasMatch()) {
\r
104 QString libName = matchLib.captured(1);
\r
105 libName = libName.toLower();
\r
107 cout << "matching library: " << qPrintable(libName) << endl;
\r
109 if (!packages.contains(libName)) {
\r
110 packages.insert(libName,new QList<QString>());
\r
113 else if (matchPack.hasMatch()) {
\r
114 cout << "matching packages" << endl;
\r
116 QString libName = matchPack.captured(1);
\r
117 QString packName = matchPack.captured(2);
\r
119 libName = libName.toLower();
\r
120 packName = packName.toLower();
\r
122 if (libName == "work") {
\r
123 if (!packages.contains("work")) {
\r
124 packages.insert("work",new QList<QString>());
\r
127 else if (libName == "std") {
\r
128 if (!packages.contains("std")) {
\r
129 packages.insert("std",new QList<QString>());
\r
132 else if (!packages.contains(libName)) throw(Exception(VHDLFILE_CORRUPTED));
\r
134 QList<QString>* lstPack = packages.value(libName);
\r
135 lstPack->append(packName);
\r
136 cout << qPrintable(packName) << endl;
\r
140 line = skipBlankAndComments(in);
\r
142 throw(Exception(VHDLFILE_CORRUPTED));
\r
144 cout << "read line = " << qPrintable(line) << endl;
\r
150 QString VHDLConverter::readEntity(QTextStream &in) throw(Exception) {
\r
152 QRegularExpression rxGen("^generic[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);
\r
153 QRegularExpression rxPorts("^port[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption);
\r
157 line = skipBlankAndComments(in);
\r
159 throw(Exception(VHDLFILE_CORRUPTED));
\r
162 while (! line.startsWith("architecture",Qt::CaseInsensitive)) {
\r
164 QRegularExpressionMatch matchGen = rxGen.match(line);
\r
165 QRegularExpressionMatch matchPorts = rxPorts.match(line);
\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
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
184 line = skipBlankAndComments(in);
\r
186 throw(Exception(VHDLFILE_CORRUPTED));
\r
188 cout << "read line = " << qPrintable(line) << endl;
\r
194 void VHDLConverter::readGenerics(QTextStream &in) throw(Exception) {
\r
196 QRegularExpression rxGen("^([^:]+):([^:]+)(:=)?([^;]*);?$",QRegularExpression::CaseInsensitiveOption);
\r
200 line = skipBlankAndComments(in);
\r
202 throw(Exception(VHDLFILE_CORRUPTED));
\r
204 line = line.remove(' ');
\r
206 while (! line.contains(QRegExp("\\);"))) {
\r
208 QRegularExpressionMatch matchGen = rxGen.match(line);
\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
222 line = skipBlankAndComments(in);
\r
224 throw(Exception(VHDLFILE_CORRUPTED));
\r
226 line = line.remove(' ');
\r
227 cout << "read line = " << qPrintable(line) << endl;
\r
231 void VHDLConverter::readPorts(QTextStream &in) throw(Exception) {
\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
239 line = skipBlankAndComments(in);
\r
241 throw(Exception(VHDLFILE_CORRUPTED));
\r
244 while (! line.contains(QRegExp("^\\);$"))) {
\r
246 line = line.toLower();
\r
248 QRegularExpressionMatch matchPort = rxPort.match(line);
\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
260 int direction = AbstractInterface::AnyDirection;
\r
261 int endianess = AbstractInterface::LittleEndian;
\r
262 int purpose = AbstractInterface::AnyPurpose;
\r
264 QString widthStr = "a";
\r
266 if (portDir == "in") {
\r
267 direction = AbstractInterface::Input;
\r
269 else if (portDir == "out") {
\r
270 direction = AbstractInterface::Output;
\r
272 else if (portDir == "inout") {
\r
273 direction = AbstractInterface::InOut;
\r
276 cerr << "Unknown direction for port " << qPrintable(portName) << endl;
\r
279 QString typeStr="";
\r
280 if (portType == "std_logic") {
\r
281 typeStr = "boolean";
\r
284 else if (portType == "std_logic_vector") {
\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
294 widthStr = matchSize.captured(1);
\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
305 widthStr = matchSize.captured(2);
\r
309 cerr << "invalid size for port " << qPrintable(portName) << endl;
\r
313 QVariant msb(widthStr);
\r
315 int size = msb.toInt(&ok);
\r
317 typeStr = "natural";
\r
320 typeStr ="expression";
\r
324 cerr << "Unknown type for port " << qPrintable(portName) << endl;
\r
329 // trying to guess the purpose from name
\r
330 if ((portName.contains("clk"))||(portName.contains("clock"))) {
\r
331 purpose = AbstractInterface::Clock;
\r
333 else if ((portName.contains("rst"))||(portName.contains("reset"))) {
\r
334 purpose = AbstractInterface::Reset;
\r
336 else if (portName.endsWith("_enb")) {
\r
337 purpose = AbstractInterface::Control;
\r
339 else if (portName.startsWith("wb_")) {
\r
340 purpose = AbstractInterface::Wishbone;
\r
343 purpose = AbstractInterface::Data;
\r
345 iface = new ReferenceInterface(block,portName,direction,purpose,typeStr,widthStr,endianess,1);
\r
346 block->addInterface(iface);
\r
350 line = skipBlankAndComments(in);
\r
352 throw(Exception(VHDLFILE_CORRUPTED));
\r
354 cout << "read line = " << qPrintable(line) << endl;
\r
359 void VHDLConverter::readArchitecture(QTextStream &in) throw(Exception) {
\r
362 QString endLine1 = "end "+archName;
\r
363 QString endLine2 = "end architecture "+archName;
\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
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
381 QString fileName = QFileDialog::getOpenFileName(this,
\r
382 tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)"));
\r
383 QFile file(fileName);
\r
385 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
\r
387 QTextStream ts(&file);
\r
389 block = new ReferenceBlock(fileName);
\r
391 QString entityLine = "";
\r
393 entityLine = readLibraries(ts);
\r
395 catch(Exception e) {
\r
396 cerr << "VHDL seems to be malformed" << endl;
\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
406 entityName = matchEnt.captured(1);
\r
407 cout << "found entity " << qPrintable(entityName) << endl;
\r
409 QString archLine = "";
\r
411 archLine = readEntity(ts);
\r
413 catch(Exception e) {
\r
414 cerr << "VHDL seems to be malformed" << endl;
\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
424 archName = matchArch.captured(1);
\r
425 cout << "found arch " << qPrintable(archName) << " for entity " << qPrintable(matchArch.captured(2)) << endl;
\r
428 readArchitecture(ts);
\r
430 catch(Exception e) {
\r
431 cerr << "VHDL seems to be malformed" << endl;
\r
437 QList<BlockParameter*> lstGenerics = block->getGenericParameters();
\r
438 twGenerics->setRowCount(lstGenerics.size());
\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
447 lstIface = block->getInputs();
\r
448 lstIface.append(block->getOutputs());
\r
449 lstIface.append(block->getBidirs());
\r
451 twPorts->setRowCount(lstIface.size());
\r
452 purposeDelegate = new IfacePurposeDelegate();
\r
453 twPorts->setItemDelegateForColumn(3,purposeDelegate);
\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
464 widthStr = "std_logic_vector(";
\r
465 if (iface->getEndianess() == AbstractInterface::LittleEndian) {
\r
466 widthStr += iface->getWidthString();
\r
467 widthStr += " downto 0)";
\r
470 widthStr += "0 to ";
\r
471 widthStr += iface->getWidthString();
\r
475 twPorts->setItem(i, 2, new QTableWidgetItem(widthStr));
\r
477 QTableWidgetItem* item = new QTableWidgetItem(iface->getPurposeString());
\r
478 twPorts->setItem(i, 3, item);
\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
492 QTableWidgetItem* itemAsso = new QTableWidgetItem(assoInter);
\r
493 if (iface->getPurpose() != AbstractInterface::Control) {
\r
494 itemAsso->setFlags(Qt::NoItemFlags);
\r
496 twPorts->setItem(i, 4, itemAsso);
\r
501 connect(twPorts,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(searchAssociatedPort(QTableWidgetItem*)));
\r
505 //scrollPorts->setWidget(twPorts);
\r
506 editEntityName->setText(entityName);
\r
507 editLongName->setText(entityName);
\r
511 void VHDLConverter::searchAssociatedPort(QTableWidgetItem *item) {
\r
514 int col = item->column();
\r
515 int row = item->row();
\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
529 QString assoInter = "N/A";
\r
530 iface->setAssociatedIface(NULL);
\r
532 cout << qPrintable(item->text()) << endl;
\r
534 if (item->text() == "data") {
\r
535 iface->setPurpose(AbstractInterface::Data);
\r
537 else if (item->text() == "control") {
\r
538 iface->setPurpose(AbstractInterface::Control);
\r
540 else if (item->text() == "clock") {
\r
541 iface->setPurpose(AbstractInterface::Clock);
\r
543 else if (item->text() == "reset") {
\r
544 iface->setPurpose(AbstractInterface::Reset);
\r
546 else if (item->text() == "wishbone") {
\r
547 iface->setPurpose(AbstractInterface::Wishbone);
\r
550 if (item->text() == "control") {
\r
552 QString name = twPorts->item(row,0)->text();
\r
553 name.remove(name.size()-4,4); // remove _enb at the end
\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
564 QTableWidgetItem* itemAsso = twPorts->item(row,4);
\r
565 itemAsso->setText(assoInter);
\r
567 if (item->text() == "control") {
\r
568 itemAsso->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable);
\r
571 itemAsso->setFlags(Qt::NoItemFlags);
\r
574 else if (col == 4) {
\r
576 QString nameAsso = item->text();
\r
577 if (nameAsso == "N/A") return;
\r
579 bool found = false;
\r
582 foreach(AbstractInterface* inter, lstIface) {
\r
583 if ((i != row) && (inter->getName().contains(nameAsso))) {
\r
585 iface->setAssociatedIface(inter);
\r
589 QTableWidgetItem* itemAsso = twPorts->item(row,4);
\r
590 itemAsso->setText("N/A");
\r
595 void VHDLConverter::generateRefXml(QDomDocument& doc) {
\r
597 QDomElement eBlock = doc.createElement("block");
\r
598 eBlock.setAttribute("version", "0.1");
\r
599 doc.appendChild(eBlock);
\r
602 QDomElement infos = doc.createElement("informations");
\r
603 eBlock.appendChild(infos);
\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
610 QDomElement category = doc.createElement("category");
\r
611 category.setAttribute("ids","");
\r
612 infos.appendChild(category);
\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
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
629 infos.appendChild(eDesc);
\r
633 QDomElement parameters = doc.createElement("parameters");
\r
634 eBlock.appendChild(parameters);
\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
646 QDomElement interfaces = doc.createElement("interfaces");
\r
647 eBlock.appendChild(interfaces);
\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
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
665 QDomElement ctl = doc.createElement("control");
\r
666 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
667 inputs.appendChild(ctl);
\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
687 QDomElement ctl = doc.createElement("control");
\r
688 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
689 outputs.appendChild(ctl);
\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
709 QDomElement ctl = doc.createElement("control");
\r
710 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
711 bidirs.appendChild(ctl);
\r
717 void VHDLConverter::generateImplXml(QDomDocument& doc) {
\r
719 QRegularExpression rxPack("^([^.]+)[.](.+)$",QRegularExpression::CaseInsensitiveOption);
\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
727 QDomElement comments = doc.createElement("comments");
\r
728 eBlock.appendChild(comments);
\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
736 QDomElement date = doc.createElement("date");
\r
737 date.setAttribute("creation","");
\r
738 comments.appendChild(date);
\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
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
755 QDomElement libs = doc.createElement("libraries");
\r
756 eBlock.appendChild(libs);
\r
758 QHashIterator<QString,QList<QString>* > it(packages);
\r
760 while (it.hasNext()) {
\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
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
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
790 archi.appendChild(tName);
\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
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
817 patterns.appendChild(prod);
\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
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,"<=");
\r
837 //line.replace(rxGT,"=>");
\r
838 archLines.replace(i,line);
\r
839 cout << qPrintable(line) << endl;
\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
847 updateArchitecture();
\r
849 // creating reference xml
\r
850 QDomDocument docRef(entityName);
\r
851 generateRefXml(docRef);
\r
853 // creating implementation xml
\r
854 QDomDocument docImpl(entityName);
\r
855 generateImplXml(docImpl);
\r
857 QString dir = QFileDialog::getExistingDirectory(this,tr("Save file in"),".",QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
\r
859 QString fileName = dir + "/"+ entityName + ".xml";
\r
861 QFile fileRef(fileName);
\r
862 if(!fileRef.open(QIODevice::WriteOnly | QIODevice::Text)) {
\r
863 cerr << "Cannot save in " << qPrintable(fileName) << endl;
\r
866 QTextStream tsRef(&fileRef);
\r
867 docRef.save(tsRef,QDomNode::EncodingFromTextStream);
\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
876 QTextStream tsImpl(&fileImpl);
\r
877 docImpl.save(tsImpl,QDomNode::EncodingFromTextStream);
\r