X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/fc9f5b8b77edda9e49a35d8ef75c4d71caf1c832..df84660fd98b39737692d57b68c8b2c2d34af0f1:/VHDLConverter.cpp?ds=inline diff --git a/VHDLConverter.cpp b/VHDLConverter.cpp index d32ab15..42fff3a 100644 --- a/VHDLConverter.cpp +++ b/VHDLConverter.cpp @@ -1,70 +1,66 @@ #include "VHDLConverter.h" +#include "BlockParameterGeneric.h" +#include "BlockParameterUser.h" +#include "BlockParameterWishbone.h" +#include "ReferenceInterface.h" using namespace std; using namespace Qt; VHDLConverter::VHDLConverter(QWidget *parent) : QWidget(parent) { - rxComment = new QRegExp("(.*)--.*"); - rxComma = new QRegExp("(.*)[;]"); - rxPort = new QRegExp("[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(in|out|inout)[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp); - rxEnt = new QRegExp("[\\s\\t]*entity[\\s\\t]*(.*)[\\s\\t]*is",CaseInsensitive,QRegExp::RegExp); - rxArch = new QRegExp("[\\s\\t]*architecture[\\s\\t]*(.*)[\\s\\t]*of (.*)[\\s\\t]*is",CaseInsensitive,QRegExp::RegExp); - rxComp = new QRegExp("[\\s\\t]*component[\\s\\t]*(.*)[\\s\\t]*",CaseInsensitive,QRegExp::RegExp); - rxEnd = new QRegExp("[\\s\\t]*end(.*)",CaseInsensitive,QRegExp::RegExp); - rxComp = new QRegExp("[\\s\\t]*end component;",CaseInsensitive,QRegExp::RegExp); - rxGeneric = new QRegExp("[\\s\\t]*generic[\\s\\t]*[(][\\s\\t]*",CaseInsensitive,QRegExp::RegExp); - rxEndGen = new QRegExp("[\\s\\t]*[)]",CaseInsensitive,QRegExp::RegExp); - rxGen = new QRegExp("[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(.*)[\\s\\t]*:=[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp); - rxConst = new QRegExp("[\\s\\t]*constant[\\s\\t]*(.*)[\\s\\t]*:[\\s\\t]*(.)*[\\s\\t]*:=[\\s\\t]*(.*)",CaseInsensitive,QRegExp::RegExp); - rxWidth = new QRegExp(".*[(](.*)(downto|to)(.*)[)]",CaseInsensitive,QRegExp::RegExp); - - QLabel *labelAppli, *lblBrief, *lblDesc, *lblName, *lblPort, *lblGen; - - loadBut = new QPushButton("load VHDL"); - genBut = new QPushButton("generate XML"); - QHBoxLayout *widgetLayout = new QHBoxLayout; - QVBoxLayout *left = new QVBoxLayout; - QVBoxLayout *right = new QVBoxLayout; - - scrollDataPort = new QScrollArea; - scrollDataPort->setWidgetResizable(true); - twDataPort = new QTableWidget(this); - scrollDataPort->setWidget(twDataPort); - scrollGenerics = new QScrollArea; - scrollGenerics->setWidgetResizable(true); - twGenerics = new QTableWidget(this); - scrollGenerics->setWidget(twGenerics); - teName = new QTextEdit; - teBrief = new QTextEdit; - teDesc = new QTextEdit; - lblName = new QLabel("Block name :"); - lblBrief = new QLabel("Enter a brief description : "); - lblDesc = new QLabel("Enter a detailled description : "); - lblPort = new QLabel("Ports :"); - lblGen = new QLabel("Generics :"); - - connect(loadBut, SIGNAL(clicked()),this, SLOT(loadVHDLFile())); - connect(genBut, SIGNAL(clicked()), this, SLOT(generateXml())); - - left->addWidget(loadBut); - left->addWidget(lblPort); - left->addWidget(scrollDataPort); - left->addWidget(lblGen); - left->addWidget(scrollGenerics); - - right->addWidget(lblName); - right->addWidget(teName); - right->addWidget(lblBrief); - right->addWidget(teBrief); - right->addWidget(lblDesc); - right->addWidget(teDesc); - right->addWidget(genBut); - - widgetLayout->addLayout(left); - widgetLayout->addLayout(right); - setLayout(widgetLayout); - show(); + QLabel *labelAppli, *lblBrief, *lblDesc, *lblEntName, *lblLongName, *lblPort, *lblGen; + + loadBut = new QPushButton("load VHDL"); + genBut = new QPushButton("generate XML"); + QHBoxLayout *widgetLayout = new QHBoxLayout; + QVBoxLayout *left = new QVBoxLayout; + QVBoxLayout *right = new QVBoxLayout; + + scrollPorts = new QScrollArea; + scrollPorts->setWidgetResizable(true); + twPorts = new QTableWidget(this); + twPorts->setColumnCount(5); + scrollPorts->setWidget(twPorts); + scrollGenerics = new QScrollArea; + scrollGenerics->setWidgetResizable(true); + twGenerics = new QTableWidget(this); + twGenerics->setColumnCount(3); + scrollGenerics->setWidget(twGenerics); + editEntityName = new QLineEdit; + editLongName = new QLineEdit; + teBrief = new QTextEdit; + teDesc = new QTextEdit; + lblEntName = new QLabel("Entity name :"); + lblLongName = new QLabel("Block long name :"); + lblBrief = new QLabel("Enter a brief description : "); + lblDesc = new QLabel("Enter a detailled description : "); + lblPort = new QLabel("Ports :"); + lblGen = new QLabel("Generics :"); + + connect(loadBut, SIGNAL(clicked()),this, SLOT(loadVHDLFile())); + connect(genBut, SIGNAL(clicked()), this, SLOT(generateXml())); + + left->addWidget(loadBut); + left->addWidget(lblPort); + left->addWidget(scrollPorts); + left->addWidget(lblGen); + left->addWidget(scrollGenerics); + + right->addWidget(lblEntName); + right->addWidget(editEntityName); + right->addWidget(lblLongName); + right->addWidget(editLongName); + right->addWidget(lblBrief); + right->addWidget(teBrief); + right->addWidget(lblDesc); + right->addWidget(teDesc); + right->addWidget(genBut); + + widgetLayout->addLayout(left); + widgetLayout->addLayout(right); + setLayout(widgetLayout); + show(); } VHDLConverter::~VHDLConverter() { @@ -75,18 +71,19 @@ QString VHDLConverter::skipBlankAndComments(QTextStream &in) { QString line = ""; - // skipping blank/comment lines + // skipping blank/comment lines while ( (line.isEmpty()) || ((line.at(0) == '-') && (line.at(1) == '-')) ) { if (in.atEnd()) { return ""; } line = in.readLine(); - if (!line.isEmpty()) line = line.trimmed(); - } + if (!line.isEmpty()) line = line.simplified(); + } + line.remove(QRegularExpression("--.*$")); return line; } -void VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { +QString VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { QRegularExpression rxLib("^library[\\s\\t]*(.+);$",QRegularExpression::CaseInsensitiveOption); QRegularExpression rxPack("^use[\\s\\t]*([^.]+)[.](.+);$",QRegularExpression::CaseInsensitiveOption); @@ -95,7 +92,7 @@ void VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { line = skipBlankAndComments(in); if (line == "") { throw(Exception(VHDLFILE_CORRUPTED)); - } + } while (! line.contains("entity",Qt::CaseInsensitive)) { @@ -107,21 +104,21 @@ void VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { QString libName = matchLib.captured(1); libName = libName.toLower(); - cout << "matching library: " << qPrintable(libName) << endl; + cout << "matching library: " << qPrintable(libName) << endl; - if (!packages.contains(libName)) { - packages.insert(libName,new QList()); - } + if (!packages.contains(libName)) { + packages.insert(libName,new QList()); + } } else if (matchPack.hasMatch()) { cout << "matching packages" << endl; QString libName = matchPack.captured(1); - QString packName = matchPack.captured(2); + QString packName = matchPack.captured(2); libName = libName.toLower(); - packName = packName.toLower(); - + packName = packName.toLower(); + if (libName == "work") { if (!packages.contains("work")) { packages.insert("work",new QList()); @@ -135,9 +132,8 @@ void VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { else if (!packages.contains(libName)) throw(Exception(VHDLFILE_CORRUPTED)); QList* lstPack = packages.value(libName); - QString s = libName + "." + packName; - lstPack->append(s); - cout << qPrintable(s) << endl; + lstPack->append(packName); + cout << qPrintable(packName) << endl; } @@ -147,21 +143,229 @@ void VHDLConverter::readLibraries(QTextStream &in) throw(Exception) { } cout << "read line = " << qPrintable(line) << endl; } + + return line; } -void VHDLConverter::readEntity(QTextStream &in) throw(Exception) { - +QString VHDLConverter::readEntity(QTextStream &in) throw(Exception) { + + QRegularExpression rxGen("^generic[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption); + QRegularExpression rxPorts("^port[\\s\\t]*[(](.*)$",QRegularExpression::CaseInsensitiveOption); + + QString line = ""; + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + + while (! line.startsWith("architecture",Qt::CaseInsensitive)) { + + QRegularExpressionMatch matchGen = rxGen.match(line); + QRegularExpressionMatch matchPorts = rxPorts.match(line); + + if (matchGen.hasMatch()) { + cout << "matching generics" << endl; + if (matchGen.captured(1).length() > 0) { + cerr << "Please, modify VHDL source so that the generic list does not begin at the same line as generic (" << endl; + throw(Exception(VHDLFILE_CORRUPTED)); + } + readGenerics(in); + } + else if (matchPorts.hasMatch()) { + cout << "matching ports" << endl; + if (matchPorts.captured(1).length() > 0) { + cerr << "Please, modify VHDL source so that the port list does not begin at the same line as port (" << endl; + throw(Exception(VHDLFILE_CORRUPTED)); + } + readPorts(in); + } + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + cout << "read line = " << qPrintable(line) << endl; + } + + return line; } void VHDLConverter::readGenerics(QTextStream &in) throw(Exception) { - + + QRegularExpression rxGen("^([^:]+):([^:]+)(:=)?([^;]*);?$",QRegularExpression::CaseInsensitiveOption); + + QString line = ""; + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + line = line.remove(' '); + + while (! line.contains(QRegExp("\\);"))) { + + QRegularExpressionMatch matchGen = rxGen.match(line); + + if (matchGen.hasMatch()) { + cout << "matching generic value" << endl; + QString genName = matchGen.captured(1); + QString genType = matchGen.captured(2); + genType = genType.toLower(); + QString genValue = matchGen.captured(4); + genValue = genValue.toLower(); + cout << qPrintable(genName) << " " << qPrintable(genType) << " " << qPrintable(genValue) << endl; + BlockParameter* param = new BlockParameterGeneric(block,genName,genType,genValue); + block->addParameter(param); + } + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + line = line.remove(' '); + cout << "read line = " << qPrintable(line) << endl; + } } void VHDLConverter::readPorts(QTextStream &in) throw(Exception) { - + + QRegularExpression rxPort("^([^ :]+) ?: ?(in|out|inout) ([a-zA-Z0-9_]+) ?(\\([^:)]*\\))? ?(:=)? ?([^;]*) ?;?$",QRegularExpression::CaseInsensitiveOption); + QRegularExpression rxSizeDownTo("^\\((.*) downto (.*)\\)$",QRegularExpression::CaseInsensitiveOption); + QRegularExpression rxSizeTo("^\\((.*) to (.*)\\)$",QRegularExpression::CaseInsensitiveOption); + + QString line = ""; + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + + while (! line.contains(QRegExp("^\\);$"))) { + + line = line.toLower(); + + QRegularExpressionMatch matchPort = rxPort.match(line); + + if (matchPort.hasMatch()) { + cout << "matching port value" << endl; + QString portName = matchPort.captured(1); + QString portDir = matchPort.captured(2); + QString portType = matchPort.captured(3); + QString portSize = matchPort.captured(4); + QString portValue = matchPort.captured(6); + cout << qPrintable(portName) << "|" << qPrintable(portDir) << "|" << qPrintable(portType) << "|" << qPrintable(portSize) << "|" << qPrintable(portValue) << endl; + ReferenceInterface* iface = NULL; + bool isOk = true; + int direction = AbstractInterface::AnyDirection; + int endianess = AbstractInterface::LittleEndian; + int purpose = AbstractInterface::AnyPurpose; + + QString widthStr = "a"; + + if (portDir == "in") { + direction = AbstractInterface::Input; + } + else if (portDir == "out") { + direction = AbstractInterface::Output; + } + else if (portDir == "inout") { + direction = AbstractInterface::InOut; + } + else { + cerr << "Unknown direction for port " << qPrintable(portName) << endl; + isOk = false; + } + QString typeStr=""; + if (portType == "std_logic") { + typeStr = "boolean"; + widthStr="1"; + } + else if (portType == "std_logic_vector") { + + if (portSize.contains("downto")) { + QRegularExpressionMatch matchSize = rxSizeDownTo.match(portSize); + endianess = AbstractInterface::LittleEndian; + if (matchSize.captured(2) != "0") { + cerr << "invalid size for port " << qPrintable(portName) << endl; + isOk = false; + } + else { + widthStr = matchSize.captured(1); + } + } + else if (portSize.contains("to")) { + QRegularExpressionMatch matchSize = rxSizeTo.match(portSize); + endianess = AbstractInterface::BigEndian; + if (matchSize.captured(1) != "0") { + cerr << "invalid size for port " << qPrintable(portName) << endl; + isOk = false; + } + else { + widthStr = matchSize.captured(2); + } + } + else { + cerr << "invalid size for port " << qPrintable(portName) << endl; + isOk = false; + } + + QVariant msb(widthStr); + bool ok; + int size = msb.toInt(&ok); + if (ok) { + typeStr = "natural"; + } + else { + typeStr ="expression"; + } + } + else { + cerr << "Unknown type for port " << qPrintable(portName) << endl; + isOk = false; + } + + if (isOk) { + // trying to guess the purpose from name + if ((portName.contains("clk"))||(portName.contains("clock"))) { + purpose = AbstractInterface::Clock; + } + else if ((portName.contains("rst"))||(portName.contains("reset"))) { + purpose = AbstractInterface::Reset; + } + else if (portName.endsWith("_enb")) { + purpose = AbstractInterface::Control; + } + else if (portName.startsWith("wb_")) { + purpose = AbstractInterface::Wishbone; + } + else { + purpose = AbstractInterface::Data; + } + iface = new ReferenceInterface(block,portName,direction,purpose,typeStr,widthStr,endianess,1); + block->addInterface(iface); + } + } + + line = skipBlankAndComments(in); + if (line == "") { + throw(Exception(VHDLFILE_CORRUPTED)); + } + cout << "read line = " << qPrintable(line) << endl; + } + } void VHDLConverter::readArchitecture(QTextStream &in) throw(Exception) { + + QString line = ""; + QString endLine = "end "+archName; + + while (!line.startsWith(endLine)) { + line = in.readLine(); + if (!line.isEmpty()) line = line.simplified(); + archLines.append(line); + } } @@ -170,230 +374,502 @@ void VHDLConverter::readArchitecture(QTextStream &in) throw(Exception) { // You can edit the descriptions in the right, one for the brief description, the other for the detailled. void VHDLConverter::loadVHDLFile() { - QString line, portName, portType, portId, genName, genType, genValue; - QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList; - cpt = 0; - twDataPort->setColumnCount(3); - twDataPort->setRowCount(cpt); - twGenerics->setColumnCount(3); - twGenerics->setRowCount(cpt); - portNameList = new QStringList; - portTypeList = new QStringList; - portIdList = new QStringList; - genNameList = new QStringList; - genTypeList = new QStringList; - genValueList = new QStringList; - - fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), "C:", tr("Files (*.txt *.vhd)")); - QFile file(fileName); - - if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return; - QTextStream ts(&file); - - readLibraries(ts); - - /* - while (!ts.atEnd()) - { - line = ts.readLine(); - if(rxComment->indexIn(line) != -1) { - line = rxComment->cap(1); + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), QDir::homePath() , tr("Files (*.txt *.vhd)")); + QFile file(fileName); + + if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + QTextStream ts(&file); + + block = new ReferenceBlock(fileName); + + QString entityLine = ""; + try { + entityLine = readLibraries(ts); + } + catch(Exception e) { + cerr << "VHDL seems to be malformed" << endl; + return; + } + + QRegularExpression rxEnt("^entity (.+) is$",QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch matchEnt = rxEnt.match(entityLine); + if (!matchEnt.hasMatch()) { + cerr << "VHDL seems to be malformed" << endl; + return; + } + entityName = matchEnt.captured(1); + cout << "found entity " << qPrintable(entityName) << endl; + + QString archLine = ""; + try { + archLine = readEntity(ts); + } + catch(Exception e) { + cerr << "VHDL seems to be malformed" << endl; + return; + } + + QRegularExpression rxArch("^architecture (.+) of (.+) is$",QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch matchArch = rxArch.match(archLine); + if (!matchArch.hasMatch()) { + cerr << "VHDL seems to be malformed" << endl; + return; + } + archName = matchArch.captured(1); + cout << "found arch " << qPrintable(archName) << " for entity " << qPrintable(matchArch.captured(2)) << endl; + + try { + readArchitecture(ts); + } + catch(Exception e) { + cerr << "VHDL seems to be malformed" << endl; + return; + } + file.close(); + + + QList lstGenerics = block->getGenericParameters(); + twGenerics->setRowCount(lstGenerics.size()); + int i = 0; + foreach(BlockParameter* param, lstGenerics) { + twGenerics->setItem(i, 0, new QTableWidgetItem(param->getName())); + twGenerics->setItem(i, 1, new QTableWidgetItem(param->getTypeString())); + twGenerics->setItem(i, 2, new QTableWidgetItem(param->getValue().toString())); + i++; + } + + lstIface = block->getInputs(); + lstIface.append(block->getOutputs()); + lstIface.append(block->getBidirs()); + + twPorts->setRowCount(lstIface.size()); + purposeDelegate = new IfacePurposeDelegate(); + twPorts->setItemDelegateForColumn(3,purposeDelegate); + + i=0; + foreach(AbstractInterface* iface, lstIface) { + twPorts->setItem(i, 0, new QTableWidgetItem(iface->getName())); + twPorts->setItem(i, 1, new QTableWidgetItem(iface->getDirectionString())); + QString widthStr=""; + if (iface->getType() == AbstractInterface::Boolean) { + widthStr = "std_logic"; + } + else { + widthStr = "std_logic_vector("; + if (iface->getEndianess() == AbstractInterface::LittleEndian) { + widthStr += iface->getWidth(); + widthStr += " downto 0)"; + } + else { + widthStr += "0 to "; + widthStr += iface->getWidth(); + widthStr += ")"; + } + } + twPorts->setItem(i, 2, new QTableWidgetItem(widthStr)); + + QTableWidgetItem* item = new QTableWidgetItem(iface->getPurposeString()); + twPorts->setItem(i, 3, item); + + // trying to find wihch other iface this one controls + QString assoInter = "N/A"; + if (iface->getPurpose() == AbstractInterface::Control) { + QString name = iface->getName(); + name.remove(name.size()-4,4); // remove _enb at the end + foreach(AbstractInterface* inter, lstIface) { + if ((inter != iface) && (inter->getName().contains(name))) { + assoInter = inter->getName(); + iface->setAssociatedIface(inter); } + } + } + QTableWidgetItem* itemAsso = new QTableWidgetItem(assoInter); + if (iface->getPurpose() != AbstractInterface::Control) { + itemAsso->setFlags(Qt::NoItemFlags); + } + twPorts->setItem(i, 4, itemAsso); - if(rxEnt->indexIn(line)!= -1) { - - entName = rxEnt->cap(1); - teName->setText(entName); - QSize size = teName->document()->size().toSize(); - teName->setMaximumSize(size); - - while(rxEnd->indexIn(line) == -1) { - line = ts.readLine(); - if(rxComment->indexIn(line) != -1) { - line = rxComment->cap(1); - } - if(rxComma->indexIn(line) != -1) { - line = rxComma->cap(1); - } - if(rxGeneric->indexIn(line) != -1) { - while(rxEndGen->indexIn(line) == -1) { - line = ts.readLine(); - if(rxComment->indexIn(line) != -1) { - line = rxComment->cap(1); - } - if(rxComma->indexIn(line) != -1) { - line = rxComma->cap(1); - } - if(rxGen->indexIn(line) != -1) { - genName = rxGen->cap(1).simplified(); - genType = rxGen->cap(2).simplified(); - genValue = rxGen->cap(3).simplified(); - - genNameList->append(genName); - genTypeList->append(genType); - genValueList->append(genValue); - } - } - } - if(rxPort->indexIn(line) != -1) { - if(rxComment->indexIn(line) != -1) { - line = rxComment->cap(1); - } - if(rxComma->indexIn(line) != -1) { - line = rxComma->cap(1); - } - portName = rxPort->cap(1).simplified(); - portId = rxPort->cap(2).simplified(); - portType = rxPort->cap(3).simplified(); - portNameList->append(portName); - portIdList->append(portId); - portTypeList->append(portType); - } - } + i++; + } + + connect(twPorts,SIGNAL(itemChanged(QTableWidgetItem*)),this,SLOT(searchAssociatedPort(QTableWidgetItem*))); + + //file.close(); + + //scrollPorts->setWidget(twPorts); + editEntityName->setText(entityName); + editLongName->setText(entityName); + return; +} + +void VHDLConverter::searchAssociatedPort(QTableWidgetItem *item) { + + bool ok; + int col = item->column(); + int row = item->row(); + + // searching for the real interface object linked to the item + AbstractInterface* iface = NULL; + QString ifaceName = twPorts->item(row,0)->text(); + foreach(AbstractInterface* inter,lstIface) { + if (inter->getName() == ifaceName) { + iface = inter; + break; + } + } + + if (col == 3) { + + QString assoInter = "N/A"; + iface->setAssociatedIface(NULL); + + cout << qPrintable(item->text()) << endl; + + if (item->text() == "data") { + iface->setPurpose(AbstractInterface::Data); + } + else if (item->text() == "control") { + iface->setPurpose(AbstractInterface::Control); + } + else if (item->text() == "clock") { + iface->setPurpose(AbstractInterface::Clock); + } + else if (item->text() == "reset") { + iface->setPurpose(AbstractInterface::Reset); + } + else if (item->text() == "wishbone") { + iface->setPurpose(AbstractInterface::Wishbone); + } + + if (item->text() == "control") { + + QString name = twPorts->item(row,0)->text(); + name.remove(name.size()-4,4); // remove _enb at the end + int i=0; + foreach(AbstractInterface* inter, lstIface) { + if ((i != row) && (inter->getName().contains(name))) { + assoInter = inter->getName(); + iface->setAssociatedIface(inter); } + i++; + } } - */ - twGenerics->setRowCount(genNameList->size()); - for(int i = 0; i < genNameList->size(); i++) { - twGenerics->setItem(i, 0, new QTableWidgetItem(genNameList->at(i))); - twGenerics->setItem(i, 1, new QTableWidgetItem(genTypeList->at(i))); - twGenerics->setItem(i, 2, new QTableWidgetItem(genValueList->at(i))); + QTableWidgetItem* itemAsso = twPorts->item(row,4); + itemAsso->setText(assoInter); + + if (item->text() == "control") { + itemAsso->setFlags(Qt::ItemIsEnabled|Qt::ItemIsEditable); } - twDataPort->setRowCount(portNameList->size()); - for(int i = 0; i < portNameList->size(); i++) { - twDataPort->setItem(i, 0, new QTableWidgetItem(portIdList->at(i))); - twDataPort->setItem(i, 1, new QTableWidgetItem(portNameList->at(i))); - twDataPort->setItem(i, 2, new QTableWidgetItem(portTypeList->at(i))); + else { + itemAsso->setFlags(Qt::NoItemFlags); } + } + else if (col == 4) { - file.close(); - scrollDataPort->setWidget(twDataPort); - return; + QString nameAsso = item->text(); + if (nameAsso == "N/A") return; + + bool found = false; + + int i=0; + foreach(AbstractInterface* inter, lstIface) { + if ((i != row) && (inter->getName().contains(nameAsso))) { + found = true; + iface->setAssociatedIface(inter); + } + } + if (!found) { + QTableWidgetItem* itemAsso = twPorts->item(row,4); + itemAsso->setText("N/A"); + } + } } -// This function gets the informations in the table and the descriptions, and creates a XML file with this content -void VHDLConverter::generateXml() { +void VHDLConverter::generateRefXml(QDomDocument& doc) { + + QDomElement eBlock = doc.createElement("block"); + eBlock.setAttribute("version", "0.1"); + doc.appendChild(eBlock); + + // creating infos + QDomElement infos = doc.createElement("informations"); + eBlock.appendChild(infos); + + QDomElement eName = doc.createElement("name"); + QDomText tName = doc.createTextNode(editLongName->text()); + eName.appendChild(tName); + infos.appendChild(eName); + + QDomElement category = doc.createElement("category"); + category.setAttribute("ids",""); + infos.appendChild(category); + + QDomElement eDesc = doc.createElement("description"); + QString brief = teBrief->toPlainText(); + QString detailed = teDesc->toPlainText(); + QDomElement eBrief = doc.createElement("brief"); + if(!brief.isEmpty()) { + QDomText txtBrief = doc.createTextNode(brief); + eBrief.appendChild(txtBrief); + eDesc.appendChild(eBrief); + } + QDomElement eDetailed = doc.createElement("detailed"); + if(!detailed.isEmpty()) { + QDomText txtDetailed = doc.createTextNode(detailed); + eDetailed.appendChild(txtDetailed); + eDesc.appendChild(eDetailed); + } + infos.appendChild(eDesc); + + - QString portName, portType, portId, genName, genType, genValue; - QStringList *portNameList, *portTypeList, *portIdList, *genNameList, *genTypeList, *genValueList; - int x, y, width; - brief = teBrief->toPlainText(); - desc = teDesc->toPlainText(); - entName = teName->toPlainText(); - - portNameList = new QStringList; - portTypeList = new QStringList; - portIdList = new QStringList; - genNameList = new QStringList; - genTypeList = new QStringList; - genValueList = new QStringList; - for(int i = 0; i < twGenerics->rowCount(); i++) { - genNameList->append(twGenerics->item(i,0)->text()); - genTypeList->append(twGenerics->item(i,1)->text()); - genValueList->append(twGenerics->item(i,2)->text()); - } - - for(int i = 0; i < twDataPort->rowCount(); i++) { - portIdList->append(twDataPort->item(i,0)->text()); - portNameList->append(twDataPort->item(i,1)->text()); - portTypeList->append(twDataPort->item(i,2)->text()); - } - - QDomDocument doc (entName); - QDomElement block = doc.createElement("block"); - block.setAttribute("name",entName); - block.setAttribute("version", "0.1"); - doc.appendChild(block); - - QDomElement comments = doc.createElement("comments"); - QDomElement category = doc.createElement("caterory"); - category.setAttribute("ids",""); - comments.appendChild(category); - - QDomElement eBrief = doc.createElement("brief"); - if(!brief.isEmpty()) { - QDomText txtBrief = doc.createTextNode(brief); - eBrief.appendChild(txtBrief); - comments.appendChild(eBrief); - } - QDomElement eDesc = doc.createElement("description"); - if(!desc.isEmpty()) { - QDomText txtDesc = doc.createTextNode(desc); - eDesc.appendChild(txtDesc); - comments.appendChild(eDesc); - } - block.appendChild(comments); - - QDomElement parameters = doc.createElement("parameters"); - QDomElement interfaces = doc.createElement("interfaces"); + QDomElement parameters = doc.createElement("parameters"); + eBlock.appendChild(parameters); + + QList lstGenerics = block->getGenericParameters(); + foreach(BlockParameter* param, lstGenerics) { + QDomElement parameter = doc.createElement("parameter"); + parameter.setAttribute("name",param->getName()); + parameter.setAttribute("type",param->getTypeString()); + parameter.setAttribute("value",param->getValue().toString()); + parameter.setAttribute("context","generic"); + parameters.appendChild(parameter); + } + + QDomElement interfaces = doc.createElement("interfaces"); + eBlock.appendChild(interfaces); + + if (block->getInputs().size() > 0) { QDomElement inputs = doc.createElement("inputs"); - QDomElement outputs = doc.createElement("outputs"); - QDomElement bidirs = doc.createElement("bidirs"); - block.appendChild(parameters); - block.appendChild(interfaces); interfaces.appendChild(inputs); + foreach(AbstractInterface* iface, block->getInputs()) { + + if (iface->getPurpose() != AbstractInterface::Control) { + QDomElement input = doc.createElement("input"); + input.setAttribute("name",iface->getName()); + input.setAttribute("type",iface->getTypeString()); + input.setAttribute("width",iface->getWidth()); + input.setAttribute("multiplicity","1"); + input.setAttribute("purpose",iface->getPurposeString()); + input.setAttribute("endian",iface->getEndianessString()); + inputs.appendChild(input); + } + else { + QDomElement ctl = doc.createElement("control"); + ctl.setAttribute("iface",iface->getAssociatedIface()->getName()); + inputs.appendChild(ctl); + } + } + } + + if (block->getOutputs().size() > 0) { + QDomElement outputs = doc.createElement("outputs"); interfaces.appendChild(outputs); + foreach(AbstractInterface* iface, block->getOutputs()) { + if (iface->getPurpose() != AbstractInterface::Control) { + QDomElement output = doc.createElement("output"); + output.setAttribute("name",iface->getName()); + output.setAttribute("type",iface->getTypeString()); + output.setAttribute("width",iface->getWidth()); + output.setAttribute("multiplicity","1"); + output.setAttribute("purpose",iface->getPurposeString()); + output.setAttribute("endian",iface->getEndianessString()); + outputs.appendChild(output); + } + else { + QDomElement ctl = doc.createElement("control"); + ctl.setAttribute("iface",iface->getAssociatedIface()->getName()); + outputs.appendChild(ctl); + } + } + } + + if (block->getBidirs().size() > 0) { + QDomElement bidirs = doc.createElement("bidirs"); interfaces.appendChild(bidirs); + foreach(AbstractInterface* iface, block->getBidirs()) { + if (iface->getPurpose() != AbstractInterface::Control) { + QDomElement bidir = doc.createElement("bidir"); + bidir.setAttribute("name",iface->getName()); + bidir.setAttribute("type",iface->getTypeString()); + bidir.setAttribute("width",iface->getWidth()); + bidir.setAttribute("multiplicity","1"); + bidir.setAttribute("purpose",iface->getPurposeString()); + bidir.setAttribute("endian",iface->getEndianessString()); + bidirs.appendChild(bidir); + } + else { + QDomElement ctl = doc.createElement("control"); + ctl.setAttribute("iface",iface->getAssociatedIface()->getName()); + bidirs.appendChild(ctl); + } + } + } +} - for(int i = 0; i < twGenerics->rowCount(); i++) { - genName = genNameList->at(i); - genType = genTypeList->at(i); - genValue = genValueList->at(i); - QDomElement parameter = doc.createElement("parameter"); - parameter.setAttribute("name",genName); - parameter.setAttribute("type",genType); - parameter.setAttribute("value",genValue); - parameter.setAttribute("context","generic"); - parameters.appendChild(parameter); - } - - for(int i = 0; i < portIdList->size(); i++) { - portId = portIdList->at(i); - portName = portNameList->at(i); - portType = portTypeList->at(i); - if(rxWidth->indexIn(portType) != -1) { - x = rxWidth->cap(1).toInt(); - y = rxWidth->cap(3).toInt(); - if(x < y) - width = y - x + 1; - else if(x > y) - width = x - y + 1; - else - width = 1; - } +void VHDLConverter::generateImplXml(QDomDocument& doc) { - if(portId.compare("in", CaseInsensitive) == 0) { - QDomElement input = doc.createElement("input"); - input.setAttribute("name",portName); - input.setAttribute("width", width); - inputs.appendChild(input); - } - else if(portId.compare("out", CaseInsensitive) == 0) { - QDomElement output = doc.createElement("output"); - output.setAttribute("name",portName); - output.setAttribute("width", width); - outputs.appendChild(output); - } - else if(portId.compare("inout", CaseInsensitive) == 0) { - QDomElement bidir = doc.createElement("bidir"); - bidir.setAttribute("name",portName); - bidir.setAttribute("width", width); - bidirs.appendChild(bidir); - } + QRegularExpression rxPack("^([^.]+)[.](.+)$",QRegularExpression::CaseInsensitiveOption); + + QDomElement eBlock = doc.createElement("block_impl"); + eBlock.setAttribute("ref_name", entityName+".xml"); + eBlock.setAttribute("ref_md5", ""); + doc.appendChild(eBlock); + + // creating infos + QDomElement comments = doc.createElement("comments"); + eBlock.appendChild(comments); + + QDomElement author = doc.createElement("author"); + author.setAttribute("firstname",""); + author.setAttribute("lastname",""); + author.setAttribute("mail",""); + comments.appendChild(author); + + QDomElement date = doc.createElement("date"); + date.setAttribute("creation",""); + comments.appendChild(date); + + QString brief = teBrief->toPlainText(); + QString detailed = teDesc->toPlainText(); + QDomElement eDesc = doc.createElement("description"); + if(!brief.isEmpty()) { + QDomText txtBrief = doc.createTextNode(brief); + eDesc.appendChild(txtBrief); + comments.appendChild(eDesc); + } + QDomElement eNotes = doc.createElement("notes"); + if(!detailed.isEmpty()) { + QDomText txtDetailed = doc.createTextNode(detailed); + eNotes.appendChild(txtDetailed); + comments.appendChild(eNotes); + } + + QDomElement libs = doc.createElement("libraries"); + eBlock.appendChild(libs); + + QHashIterator* > it(packages); + + while (it.hasNext()) { + it.next(); + QString libName = it.key(); + cout << qPrintable(libName) << endl; + QList* packList = it.value(); + QDomElement lib = doc.createElement("library"); + lib.setAttribute("name", libName); + libs.appendChild(lib); + + foreach(QString packName, *packList) { + QDomElement pack = doc.createElement("package"); + lib.appendChild(pack); + QRegularExpressionMatch matchPack = rxPack.match(packName); + if (matchPack.hasMatch()) { + QString name = matchPack.captured(1); + QString subName = matchPack.captured(2); + name = name.toLower(); + subName = subName.toLower(); + pack.setAttribute("name",name); + pack.setAttribute("use",subName); + } } + } + + QDomElement archi = doc.createElement("architecture"); + eBlock.appendChild(archi); + QDomText tName = doc.createTextNode(""); + foreach(QString line, archLines) { + tName.appendData(line+"\n"); + } + archi.appendChild(tName); + + QDomElement patterns = doc.createElement("patterns"); + eBlock.appendChild(patterns); + QDomElement delta = doc.createElement("delta"); + delta.setAttribute("value","to_define"); + patterns.appendChild(delta); + QDomElement cons = doc.createElement("consumption"); + foreach(AbstractInterface* iface, lstIface) { + if ((iface->getDirection() == AbstractInterface::Input) && (iface->getPurpose() == AbstractInterface::Control)) { + QDomElement input = doc.createElement("input"); + input.setAttribute("name",iface->getName()); + input.setAttribute("pattern","to_define"); + cons.appendChild(input); + } + } + patterns.appendChild(cons); + QDomElement prod = doc.createElement("production"); + prod.setAttribute("counter","to_define"); + foreach(AbstractInterface* iface, lstIface) { + if ((iface->getDirection() == AbstractInterface::Output) && (iface->getPurpose() == AbstractInterface::Control)) { + QDomElement output = doc.createElement("output"); + output.setAttribute("name",iface->getName()); + output.setAttribute("pattern","to_define"); + prod.appendChild(output); + } + } + patterns.appendChild(prod); +} - fileName = QFileDialog::getOpenFileName(this, tr("Open File"), - "C:", tr("Files (*.xml)")); - QFile file(fileName); - if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) - return; - QTextStream ts(&file); - doc.save(ts,QDomNode::EncodingFromTextStream); - file.close(); +void VHDLConverter::replaceSignalNames(QString& line) { + foreach(AbstractInterface* iface, lstIface) { + QString pattern = iface->getName() + "([^a-zA-Z0-9_])"; + QString repl = "@{"+iface->getName()+"}\\1"; + QRegularExpression rxPort(pattern,QRegularExpression::CaseInsensitiveOption); + line.replace(rxPort,repl); + } + +} + +void VHDLConverter::updateArchitecture() { + QRegularExpression rxLT("<=",QRegularExpression::CaseInsensitiveOption); + QRegularExpression rxGT("=>",QRegularExpression::CaseInsensitiveOption); + foreach(QString line, archLines) { + replaceSignalNames(line); + line.replace(rxLT,"<="); + line.replace(rxGT,"=>"); + + cout << qPrintable(line) << endl; + } +} + +// This function gets the informations in the table and the descriptions, and creates a XML file with this content +void VHDLConverter::generateXml() { + + + updateArchitecture(); + + // creating reference xml + QDomDocument docRef(entityName); + generateRefXml(docRef); + + // creating implementation xml + QDomDocument docImpl(entityName); + generateImplXml(docImpl); + + QString dir = QFileDialog::getExistingDirectory(this,tr("Save file in"),".",QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + + QString fileName = dir + "/"+ entityName + ".xml"; + + QFile fileRef(fileName); + if(!fileRef.open(QIODevice::WriteOnly | QIODevice::Text)) { + cerr << "Cannot save in " << qPrintable(fileName) << endl; + return; + } + QTextStream tsRef(&fileRef); + docRef.save(tsRef,QDomNode::EncodingFromTextStream); + fileRef.close(); + + fileName = dir + "/"+ entityName + "_impl.xml"; + QFile fileImpl(fileName); + if(!fileImpl.open(QIODevice::WriteOnly | QIODevice::Text)) { + cerr << "Cannot save in " << qPrintable(fileName) << endl; + return; + } + QTextStream tsImpl(&fileImpl); + docImpl.save(tsImpl,QDomNode::EncodingFromTextStream); + fileImpl.close(); - QLabel *popup = new QLabel("Votre fichier XML est rempli"); - popup->show(); }