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 endLine = "end "+archName;
\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
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
377 QString fileName = QFileDialog::getOpenFileName(this,
\r
378 tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)"));
\r
379 QFile file(fileName);
\r
381 if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
\r
383 QTextStream ts(&file);
\r
385 block = new ReferenceBlock(fileName);
\r
387 QString entityLine = "";
\r
389 entityLine = readLibraries(ts);
\r
391 catch(Exception e) {
\r
392 cerr << "VHDL seems to be malformed" << endl;
\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
402 entityName = matchEnt.captured(1);
\r
403 cout << "found entity " << qPrintable(entityName) << endl;
\r
405 QString archLine = "";
\r
407 archLine = readEntity(ts);
\r
409 catch(Exception e) {
\r
410 cerr << "VHDL seems to be malformed" << endl;
\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
420 archName = matchArch.captured(1);
\r
421 cout << "found arch " << qPrintable(archName) << " for entity " << qPrintable(matchArch.captured(2)) << endl;
\r
424 readArchitecture(ts);
\r
426 catch(Exception e) {
\r
427 cerr << "VHDL seems to be malformed" << endl;
\r
433 QList<BlockParameter*> lstGenerics = block->getGenericParameters();
\r
434 twGenerics->setRowCount(lstGenerics.size());
\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
443 lstIface = block->getInputs();
\r
444 lstIface.append(block->getOutputs());
\r
445 lstIface.append(block->getBidirs());
\r
447 twPorts->setRowCount(lstIface.size());
\r
448 purposeDelegate = new IfacePurposeDelegate();
\r
449 twPorts->setItemDelegateForColumn(3,purposeDelegate);
\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
460 widthStr = "std_logic_vector(";
\r
461 if (iface->getEndianess() == AbstractInterface::LittleEndian) {
\r
462 widthStr += iface->getWidth();
\r
463 widthStr += " downto 0)";
\r
466 widthStr += "0 to ";
\r
467 widthStr += iface->getWidth();
\r
471 twPorts->setItem(i, 2, new QTableWidgetItem(widthStr));
\r
473 QTableWidgetItem* item = new QTableWidgetItem(iface->getPurposeString());
\r
474 twPorts->setItem(i, 3, item);
\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
488 QTableWidgetItem* itemAsso = new QTableWidgetItem(assoInter);
\r
489 if (iface->getPurpose() != AbstractInterface::Control) {
\r
490 itemAsso->setFlags(Qt::NoItemFlags);
\r
492 twPorts->setItem(i, 4, itemAsso);
\r
497 connect(twPorts,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(searchAssociatedPort(QTableWidgetItem*)));
\r
501 //scrollPorts->setWidget(twPorts);
\r
502 editEntityName->setText(entityName);
\r
503 editLongName->setText(entityName);
\r
507 void VHDLConverter::searchAssociatedPort(QTableWidgetItem *item) {
\r
510 int col = item->column();
\r
511 int row = item->row();
\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
525 QString assoInter = "N/A";
\r
526 iface->setAssociatedIface(NULL);
\r
528 cout << qPrintable(item->text()) << endl;
\r
530 if (item->text() == "data") {
\r
531 iface->setPurpose(AbstractInterface::Data);
\r
533 else if (item->text() == "control") {
\r
534 iface->setPurpose(AbstractInterface::Control);
\r
536 else if (item->text() == "clock") {
\r
537 iface->setPurpose(AbstractInterface::Clock);
\r
539 else if (item->text() == "reset") {
\r
540 iface->setPurpose(AbstractInterface::Reset);
\r
542 else if (item->text() == "wishbone") {
\r
543 iface->setPurpose(AbstractInterface::Wishbone);
\r
546 if (item->text() == "control") {
\r
548 QString name = twPorts->item(row,0)->text();
\r
549 name.remove(name.size()-4,4); // remove _enb at the end
\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
560 QTableWidgetItem* itemAsso = twPorts->item(row,4);
\r
561 itemAsso->setText(assoInter);
\r
563 if (item->text() == "control") {
\r
564 itemAsso->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable);
\r
567 itemAsso->setFlags(Qt::NoItemFlags);
\r
570 else if (col == 4) {
\r
572 QString nameAsso = item->text();
\r
573 if (nameAsso == "N/A") return;
\r
575 bool found = false;
\r
578 foreach(AbstractInterface* inter, lstIface) {
\r
579 if ((i != row) && (inter->getName().contains(nameAsso))) {
\r
581 iface->setAssociatedIface(inter);
\r
585 QTableWidgetItem* itemAsso = twPorts->item(row,4);
\r
586 itemAsso->setText("N/A");
\r
591 void VHDLConverter::generateRefXml(QDomDocument& doc) {
\r
593 QDomElement eBlock = doc.createElement("block");
\r
594 eBlock.setAttribute("version", "0.1");
\r
595 doc.appendChild(eBlock);
\r
598 QDomElement infos = doc.createElement("informations");
\r
599 eBlock.appendChild(infos);
\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
606 QDomElement category = doc.createElement("category");
\r
607 category.setAttribute("ids","");
\r
608 infos.appendChild(category);
\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
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
625 infos.appendChild(eDesc);
\r
629 QDomElement parameters = doc.createElement("parameters");
\r
630 eBlock.appendChild(parameters);
\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
642 QDomElement interfaces = doc.createElement("interfaces");
\r
643 eBlock.appendChild(interfaces);
\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
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
661 QDomElement ctl = doc.createElement("control");
\r
662 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
663 inputs.appendChild(ctl);
\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
683 QDomElement ctl = doc.createElement("control");
\r
684 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
685 outputs.appendChild(ctl);
\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
705 QDomElement ctl = doc.createElement("control");
\r
706 ctl.setAttribute("iface",iface->getAssociatedIface()->getName());
\r
707 bidirs.appendChild(ctl);
\r
713 void VHDLConverter::generateImplXml(QDomDocument& doc) {
\r
715 QRegularExpression rxPack("^([^.]+)[.](.+)$",QRegularExpression::CaseInsensitiveOption);
\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
723 QDomElement comments = doc.createElement("comments");
\r
724 eBlock.appendChild(comments);
\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
732 QDomElement date = doc.createElement("date");
\r
733 date.setAttribute("creation","");
\r
734 comments.appendChild(date);
\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
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
751 QDomElement libs = doc.createElement("libraries");
\r
752 eBlock.appendChild(libs);
\r
754 QHashIterator<QString,QList<QString>* > it(packages);
\r
756 while (it.hasNext()) {
\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
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
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
786 archi.appendChild(tName);
\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
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
813 patterns.appendChild(prod);
\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
826 void VHDLConverter::updateArchitecture() {
\r
827 QRegularExpression rxLT("<=",QRegularExpression::CaseInsensitiveOption);
\r
828 QRegularExpression rxGT("=>",QRegularExpression::CaseInsensitiveOption);
\r
829 foreach(QString line, archLines) {
\r
830 replaceSignalNames(line);
\r
831 line.replace(rxLT,"<=");
\r
832 line.replace(rxGT,"=>");
\r
834 cout << qPrintable(line) << endl;
\r
838 // This function gets the informations in the table and the descriptions, and creates a XML file with this content
\r
839 void VHDLConverter::generateXml() {
\r
842 updateArchitecture();
\r
844 // creating reference xml
\r
845 QDomDocument docRef(entityName);
\r
846 generateRefXml(docRef);
\r
848 // creating implementation xml
\r
849 QDomDocument docImpl(entityName);
\r
850 generateImplXml(docImpl);
\r
852 QString dir = QFileDialog::getExistingDirectory(this,tr("Save file in"),".",QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
\r
854 QString fileName = dir + "/"+ entityName + ".xml";
\r
856 QFile fileRef(fileName);
\r
857 if(!fileRef.open(QIODevice::WriteOnly | QIODevice::Text)) {
\r
858 cerr << "Cannot save in " << qPrintable(fileName) << endl;
\r
861 QTextStream tsRef(&fileRef);
\r
862 docRef.save(tsRef,QDomNode::EncodingFromTextStream);
\r
865 fileName = dir + "/"+ entityName + "_impl.xml";
\r
866 QFile fileImpl(fileName);
\r
867 if(!fileImpl.open(QIODevice::WriteOnly | QIODevice::Text)) {
\r
868 cerr << "Cannot save in " << qPrintable(fileName) << endl;
\r
871 QTextStream tsImpl(&fileImpl);
\r
872 docImpl.save(tsImpl,QDomNode::EncodingFromTextStream);
\r