From: stephane Domas Date: Fri, 30 Mar 2018 14:41:33 +0000 (+0200) Subject: finished VHDL gen. (but have to test further X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain/14cd6d834ab531525a51c6a6992583b3e9143e02 finished VHDL gen. (but have to test further --- diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp index 7bdec1b..c1c3c38 100644 --- a/AbstractBlock.cpp +++ b/AbstractBlock.cpp @@ -312,7 +312,7 @@ void AbstractBlock::generateComponent(QTextStream& out, bool hasController) thro catch(Exception e) { throw(e); } - out << " end component " << endl << endl; + out << " end component; " << endl << endl; } diff --git a/AbstractBlock.h b/AbstractBlock.h index 5f2acb5..0ca5536 100644 --- a/AbstractBlock.h +++ b/AbstractBlock.h @@ -60,7 +60,7 @@ public: // others void connectClkReset() throw(Exception); - + virtual QList getExternalResources() = 0; // returns the list of all external files needed for VHDL generation virtual void generateVHDL(const QString& path) throw(Exception) = 0; // main entry to generate the VHDL code void generateComponent(QTextStream& out, bool hasController=false) throw(Exception); // generate the component using reference void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference diff --git a/BlockImplementation.cpp b/BlockImplementation.cpp index 23ec8bc..365ccb7 100644 --- a/BlockImplementation.cpp +++ b/BlockImplementation.cpp @@ -110,217 +110,6 @@ bool BlockImplementation::checkPatterns() { return true; } -QString BlockImplementation::eval(QString line, QTextStream& out) { - QString res, s, begLine, endLine, expr; - evaluator->setExpression(line); - QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)"); - QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)"); - QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*"); - - int nbAt = line.count('@'); - while(nbAt != 0) { - for(int i = 0; i < line.size(); i++) { - if(rxString->indexIn(line)) { - begLine = rxString->cap(1); - s = rxString->cap(2); - endLine = rxString->cap(3); - res = begLine + evalString(s) + endLine + '\n'; - nbAt --; - } - } - for(int i = 0; i < line.size(); i++) { - if(rxValue->indexIn(line)) { - begLine = rxValue->cap(1); - s = rxValue->cap(2); - endLine = rxValue->cap(3); - res = begLine + evalValue(s) + endLine + '\n'; - nbAt --; - } - } - for(int i = 0; i < line.size(); i++) { - if(rxExpr->indexIn(line)) { - expr = rxExpr->cap(1); - if(expr.count('@') == 0) { - evaluator->setExpression(expr); - s = QString::number(evaluator->evaluate()); - } - res = begLine + s + endLine + '\n'; - nbAt --; - } - } - } - return res; -} - -QString BlockImplementation::evalComplex(QString line, int id) { - QString res, s, begLine, endLine, expr; - QRegExp *rxString = new QRegExp("(.*)@{(.*)}(.*)"); - QRegExp *rxValue = new QRegExp("(.*)@val{(.*)}(.*)"); - QRegExp *rxExpr = new QRegExp(".*@eval{(.*)}.*"); - QRegExp *rxFor = new QRegExp("@foreach{.*}(@{.*})(.*)@endforeach"); - QRegExp *rxCase = new QRegExp("@caseeach{.*,(.*),(.*)}(@{.*})(.*)@endcaseeach"); - QRegExp *rxCaseDown = new QRegExp("@#-:(.*)"); - QRegExp *rxCaseUp = new QRegExp("@#:(.*)"); - evaluator->setExpression(line); - - int nbAt = line.count('@') - 2; - while(nbAt != 0) { - for(int i = 0; i < line.size(); i++) { - if(rxString->indexIn(line)) { - begLine = rxString->cap(1); - s = rxString->cap(2); - endLine = rxString->cap(3); - if(evalStringComplex(s)->size() == 0) - line = begLine + evalString(s) + endLine; - nbAt --; - } - } - for(int i = 0; i < line.size(); i++) { - if(rxValue->indexIn(line)) { - begLine = rxValue->cap(1); - s = rxValue->cap(2); - endLine = rxValue->cap(3); - line = begLine + evalValue(s) + endLine; - nbAt --; - } - } - for(int i = 0; i < line.size(); i++) { - if(rxExpr->indexIn(line)) { - expr = rxExpr->cap(1); - if(expr.count('@') == 0) { - evaluator->setExpression(expr); - s = QString::number(evaluator->evaluate()); - } - res = begLine + s + endLine + '\n'; - nbAt --; - } - } - } - - if(id == 1) { - if(rxFor->indexIn(line)) { - QString intName, instruc; - intName = rxFor->cap(1); - instruc = rxFor->cap(2); - QList *intList = evalStringComplex(intName); - if(intList->size() != 0) { - for(int i = 0; i < intList->size(); i++) { - res = intList->at(i)->getName() + instruc + '\n'; - } - } - } - } - - else if(id == 2) { - if(rxCase->indexIn(line)) { - QString intName, sigName, cases, instruc; - int number; - sigName = rxCase->cap(1); - cases = rxCase->cap(2); - intName = rxCase->cap(3); - instruc = rxCase->cap(4); - QList *intList = evalStringComplex(intName); - int listSize = intList->count(); - res = "case " + sigName + " is\n"; - if(rxCaseUp->indexIn(cases)) { - number = rxCaseUp->cap(1).toInt(); - for(int j = number; j < listSize; j++) { - if(listSize > 0) { - for(int i = 0; i < listSize; i++) { - res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n"; - } - } - else - res += "\twhen " + number + ' ' + intName + instruc + "\n"; - number++; - } - } - if(rxCaseDown->indexIn(cases)) { - number = rxCaseDown->cap(1).toInt(); - for(int j = number; j < listSize; j++) { - if(listSize > 0) { - for(int i = 0; i < listSize; i++) { - res += "\twhen " + QString::number(number) + " " + intList->at(i)->getName() + instruc + "\n"; - } - } - else - res += "\twhen " + number + ' ' + intName + instruc + "\n"; - number--; - } - res += "end case ;\n"; - } - } - } - return res; -} - -QString BlockImplementation::evalString(QString s) { - - QString name = getIfaceUserName(block->AbstractBlock::getIfaceFromName(s)); - return name; -} - -QList* BlockImplementation::evalStringComplex(QString s) { - - int j = 0; - QList *listInterfaces = new QList(); - AbstractInterface *inter = block->AbstractBlock::getIfaceFromName(s); - QList listIntBlock = block->getInterfaces(); - for(int i = 0; i < listIntBlock.size(); i++) { - if(inter->getName().compare(listIntBlock.at(i)->getName()) < -1) { - listInterfaces->insert(j, inter); - j ++; - } - } - return listInterfaces; -} - -QString BlockImplementation::evalValue(QString s) { - - QString val = ""; - if(paramMap.contains(s)) - val = paramMap.value(s); - return val; -} - -QString BlockImplementation::getIfaceUserName(AbstractInterface* refIface) { - - if (! refIface->isReferenceInterface()) return ""; - - AbstractInterface* funcIface = NULL; - - if (refIface->getDirection() == AbstractInterface::Input) { - foreach(AbstractInterface* iface, block->getInputs()) { - FunctionalInterface* fi = (FunctionalInterface*)iface; - if (fi->getReference() == refIface) { - funcIface = iface; - break; - } - } - } - else if (refIface->getDirection() == AbstractInterface::Output) { - foreach(AbstractInterface* iface, block->getOutputs()) { - FunctionalInterface* fi = (FunctionalInterface*)iface; - if (fi->getReference() == refIface) { - funcIface = iface; - break; - } - } - } - else if (refIface->getDirection() == AbstractInterface::InOut) { - foreach(AbstractInterface* iface, block->getBidirs()) { - FunctionalInterface* fi = (FunctionalInterface*)iface; - if (fi->getReference() == refIface) { - funcIface = iface; - break; - } - } - } - if (funcIface == NULL) return ""; - - return funcIface->getName(); -} - QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) { out.setVersion(QDataStream::Qt_5_0); @@ -331,6 +120,7 @@ QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) { toWrite << impl.xmlFile; toWrite << impl.referenceXml; toWrite << impl.referenceMd5; + toWrite << impl.resources; // saving patterns toWrite << impl.noPatterns; toWrite << impl.delta; @@ -354,6 +144,7 @@ QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) { in >> impl.xmlFile; in >> impl.referenceXml; in >> impl.referenceMd5; + in >> impl.resources; // loading patterns in >> impl.noPatterns; in >> impl.delta; @@ -363,38 +154,3 @@ QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) { return in; } - -QString BlockImplementation::calculateWidth(QString s){ - QRegExp *rxWidth = new QRegExp("$*([a-zA-Z0-9_-]*)"); - QStringList matchList = s.split(" "); - int pos = 0; - QString res, line; - QList listParams = reference->getParameters(); - - while ((pos = rxWidth->indexIn(s, pos)) != -1) { - matchList << rxWidth->cap(1); - pos += rxWidth->matchedLength(); - } - - for (int i = 0; i < matchList.size(); i++) { - QString match = matchList.at(i); - if(rxWidth->indexIn(match)) { - for(int j = 0; j < listParams.size(); j++) { - if(match.compare(listParams.at(j)->getName())) { - BlockParameter *param = listParams.at(i); - if(param->getContext() == "generic") { - match = match.remove('$'); - } - else { - match = param->getValue().toString(); - } - } - } - } - } - line = matchList.join(' '); - evaluator->setExpression(line); - res = evaluator->evaluate(); - return res; -} - diff --git a/BlockImplementation.h b/BlockImplementation.h index 72776e3..a9a5249 100644 --- a/BlockImplementation.h +++ b/BlockImplementation.h @@ -35,6 +35,7 @@ public: inline QHash getConsumptionPattern() { return consumptionPattern; } inline QHash getProductionPattern() { return productionPattern; } inline QString getProductionCounter() { return productionCounter; } + inline QList getResources() { return resources; } // setters inline void setDelta(QString _delta) { delta = _delta; } @@ -46,25 +47,18 @@ public: inline bool hasNoPatterns() { return noPatterns; } - QString eval(QString line, QTextStream& out); - QString evalComplex(QString line, int num); - QString evalString(QString s); - QList* evalStringComplex(QString s); - QString evalValue(QString s); - QString calculateWidth(QString s); - inline void setReference(ReferenceBlock* _reference) { reference = _reference; } void loadPatterns(QDomElement &root) throw(Exception); bool checkPatterns(); - inline void addSource(QString file) { sources.append(file); } + inline void addResource(QString file) { resources.append(file); } private: QString xmlFile; QString referenceXml; QString referenceMd5; - QList sources; + QList resources; QMap paramMap; ArithmeticEvaluator* evaluator; @@ -74,9 +68,7 @@ private: QString delta; QHash consumptionPattern; // key = reference interface name, value = pattern expression QHash productionPattern; // key = reference interface name, value = pattern expression - QString productionCounter; - - QString getIfaceUserName(AbstractInterface* refIface); // get the name of an interface given by the user, from the reference interface + QString productionCounter; friend QDataStream &operator<<(QDataStream &out, const BlockImplementation &impl); friend QDataStream &operator>>(QDataStream &in, BlockImplementation &impl); diff --git a/BlockParameterGeneric.cpp b/BlockParameterGeneric.cpp index d652c37..14b8c59 100644 --- a/BlockParameterGeneric.cpp +++ b/BlockParameterGeneric.cpp @@ -59,14 +59,33 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { formatNoValue.append(";"); } - if (!userValue.isNull()) { - ret = formatValue.arg(name).arg(getTypeString()).arg(userValue.toString()); - } - else if (!defaultValue.isNull()) { - ret = formatValue.arg(name).arg(getTypeString()).arg(defaultValue.toString()); + QString typeStr = ""; + QString valueStr = ""; + if ((type == Boolean)||(type == Bit)) { + typeStr = "std_logic"; + if (!userValue.isNull()) { + valueStr = "'"+userValue.toString()+"'"; + ret = formatValue.arg(name).arg(typeStr).arg(valueStr); + } + else if (!defaultValue.isNull()) { + valueStr = "'"+defaultValue.toString()+"'"; + ret = formatValue.arg(name).arg(typeStr).arg(valueStr); + } + else { + ret = formatNoValue.arg(name).arg(typeStr); + } } else { - ret = formatNoValue.arg(name).arg(getTypeString()); + typeStr = getTypeString(); + if (!userValue.isNull()) { + ret = formatValue.arg(name).arg(typeStr).arg(userValue.toString()); + } + else if (!defaultValue.isNull()) { + ret = formatValue.arg(name).arg(typeStr).arg(defaultValue.toString()); + } + else { + ret = formatNoValue.arg(name).arg(typeStr); + } } } else if (context == BlockParameter::Instance) { @@ -87,10 +106,20 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { } else { if (!userValue.isNull()) { - ret = format.arg(name).arg(userValue.toString()); + if ((type == Boolean)||(type == Bit)) { + ret = format.arg(name).arg("'"+userValue.toString()+"'"); + } + else { + ret = format.arg(name).arg(userValue.toString()); + } } else if (!defaultValue.isNull()) { - ret = format.arg(name).arg(defaultValue.toString()); + if ((type == Boolean)||(type == Bit)) { + ret = format.arg(name).arg("'"+defaultValue.toString()+"'"); + } + else { + ret = format.arg(name).arg(defaultValue.toString()); + } } else { // abnormal case diff --git a/DelayInputModifier.cpp b/DelayInputModifier.cpp index a90695a..a60d7e2 100644 --- a/DelayInputModifier.cpp +++ b/DelayInputModifier.cpp @@ -34,23 +34,30 @@ QString DelayInputModifier::toVHDL(int context, int flags) throw(Exception) { dm1.setNum(delayLength-1); dm2.setNum(delayLength-2); QString ret=""; + QString clkName = "clk"; + QString resetName = "reset"; + if (toIface->getOwner()->getParent()->isTopGroupBlock()) { + clkName = "from_clkrstgen_clk"; + resetName ="from_clkrstgen_reset"; + } + if (context == Architecture) { - ret = toName + "_mod_process : process(clk,reset)\n"; + ret = toName + "_mod_process : process("+clkName+","+resetName+")\n"; ret += " begin\n"; - ret += " if reset = '1' then\n"; + ret += " if "+resetName+" = '1' then\n"; ret += " "+toName+"_dly <= (others => (others => '0'));\n"; ret += " "+toCtlName+"_dly <= (others => '0');\n"; ret += " "+toName+"_mod <= (others => '0');\n"; ret += " "+toCtlName+"_mod <= '0';\n"; - ret += " elsif rising_edge(clk) then\n"; + ret += " elsif rising_edge("+clkName+") then\n"; ret += " "+toName+"_mod <= "+toName+"_dly("+dm1+");\n"; ret += " "+toCtlName+"_mod <= "+toCtlName+"_dly("+dm1+");\n"; ret += " "+toName+"_dly(0) <= "+fromIface->toVHDL(AbstractInterface::Instance,0)+";\n"; ret += " "+toCtlName+"_dly(0) <= "+fromCtlIface->toVHDL(AbstractInterface::Instance,0)+";\n"; ret += " "+toName+"_dly(1 to "+dm1+") <= "+toName+"_dly(0 to "+dm2+");\n"; ret += " "+toCtlName+"_dly(1 to "+dm1+") <= "+toCtlName+"_dly(0 to "+dm2+");\n"; - ret += " end if\n"; - ret += " end process "+toName + "_mod_process\n"; + ret += " end if;\n"; + ret += " end process "+toName + "_mod_process;\n"; } else if (context == Signal) { QString sig = toIface->toVHDL(AbstractInterface::Signal,0); diff --git a/Dispatcher.cpp b/Dispatcher.cpp index c3ff33f..b9e09a9 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -2,6 +2,8 @@ #include "Parameters.h" #include "MainWindow.h" +#include "ExternalResource.h" + #include "Graph.h" #include "ReferenceBlock.h" #include "GroupBlock.h" @@ -71,6 +73,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { QFileInfo info(filename); params->projectPath = info.absolutePath(); + params->projectName = info.baseName(); cout << "project path = " << qPrintable(params->projectPath) << endl; groupList.append(topGroup); return topGroup; @@ -174,6 +177,93 @@ void Dispatcher::changeConnectionMode(int mode){ */ } +void Dispatcher::generateVHDL() throw(Exception) { + static QString fctName = "Dispatcher::generateVHDL()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + QDir baseDir(params->projectPath); + QDir srcDir(params->projectPath+"/src"); + + if (!baseDir.exists()) { + cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl; + return; + } + + if (srcDir.exists()) { + srcDir.removeRecursively(); + } + baseDir.mkdir("src"); + + if (! baseDir.exists("testbench")) { + baseDir.mkdir("testbench"); + } + if (! baseDir.exists("Makefile")) { + QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim"); + QString dest = params->projectPath; + dest += "/Makefile"; + make.copy(dest); + } + + // copying external resources + QString dest = params->projectPath; + dest += "/src/"; + try { + params->getGraph()->generateVHDL(dest); + + QList extResources = params->getGraph()->getExternalResources(); + foreach(QString name, extResources) { + cout << qPrintable(name) << endl; + QList lstRes = params->searchResourceByName(name); + foreach(ExternalResource* res, lstRes) { + QFile resFile(res->getFile()); + QFileInfo info(res->getFile()); + QString destFile = dest+info.fileName(); + cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl; + resFile.copy(destFile); + } + } + } + catch(Exception e) { + throw(e); + } + + // creating parameters file + QString paramName = params->projectPath+"/params-isim.txt"; + QFile paramFile(paramName); + if (!paramFile.open(QIODevice::WriteOnly)) { + throw(Exception(PROJECTPATH_NOACCESS)); + } + QTextStream out(¶mFile); + out << "PROJECT_NAME := " << params->projectName << endl << endl; + out << "SRC_DIR := src" << endl; + out << "TB_DIR := testbench" << endl << endl; + out << "VHDL_SRC := "; + QStringList filter; + filter << "*.vhd" ; + srcDir.setNameFilters(filter); + QStringList listVHDL = srcDir.entryList(); + for(int j=0;j 0) { + out << "\t"; + } + out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j)); + if (j != listVHDL.size()-1) { + out << " \\"; + } + out << endl; + } + out << endl; + out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl; + out << "TB_SRC := $(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl; + out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl; + + paramFile.close(); + + +} + void Dispatcher::generateBlockVHDL(BoxItem *item){ static QString fctName = "Dispatcher::generateBlockVHDL()"; #ifdef DEBUG_FCTNAME diff --git a/Dispatcher.h b/Dispatcher.h index 538ee66..807c3bb 100644 --- a/Dispatcher.h +++ b/Dispatcher.h @@ -20,6 +20,8 @@ class ConnectionItem; class InterfaceItem; class GroupBlock; class FunctionalBlock; +#include "Exception.h" +class Exception; @@ -62,7 +64,12 @@ public: bool isCurrentProject; public slots: + + // graph ops QMap getAllGroupNames(); + void generateVHDL() throw(Exception); + + // scene ops GroupScene* getSceneById(int id); GroupScene* getSceneByName(QString name); BoxItem* getBoxItemById(int id); diff --git a/Exception.cpp b/Exception.cpp index 8c59d0d..1329f0c 100644 --- a/Exception.cpp +++ b/Exception.cpp @@ -20,6 +20,7 @@ QString Exception::getDefaultMessage() { case CONFIGFILE_NOACCESS : ret = tr("Blast configuration file cannot be read"); break; case PROJECTFILE_CORRUPTED : ret = tr("Project file is corrupted"); break; case PROJECTFILE_NOACCESS : ret = tr("Project file cannot be read"); break; + case PROJECTPATH_NOACCESS : ret = tr("Project (sub)directory or file cannot be created or accessed"); break; case BLOCKPATH_NOACCESS : ret = tr("Directory containing references cannot be accessed (no rights/existence)"); break; case IMPLPATH_NOACCESS : ret = tr("Directory containing implementations cannot be accessed (no rights/existence)"); break; case BLOCKFILE_CORRUPTED : ret = tr("Block file is corrupted"); break; diff --git a/Exception.h b/Exception.h index 608bc55..00d146a 100644 --- a/Exception.h +++ b/Exception.h @@ -25,6 +25,7 @@ supp. infos : saved in UTF-8 [éè] #define PROJECTFILE_NOACCESS 201 #define PROJECTFILE_CORRUPTED 202 +#define PROJECTPATH_NOACCESS 203 #define BLOCKFILE_NOACCESS 301 #define BLOCKFILE_CORRUPTED 302 diff --git a/ExternalResource.cpp b/ExternalResource.cpp new file mode 100644 index 0000000..4f3f7fd --- /dev/null +++ b/ExternalResource.cpp @@ -0,0 +1,9 @@ +#include "ExternalResource.h" + + +ExternalResource::ExternalResource(const QString& _name, const QString& _file, int _type) { + + name = _name; + file = _file; + type = _type; +} diff --git a/ExternalSource.h b/ExternalResource.h similarity index 76% rename from ExternalSource.h rename to ExternalResource.h index 5c244c4..e3adf1b 100644 --- a/ExternalSource.h +++ b/ExternalResource.h @@ -10,13 +10,13 @@ using namespace std; using namespace Qt; -class ExternalSource { +class ExternalResource { public : enum SourceType { Code = 1, Package, Netlist, InitFile}; - ExternalSource(const QString& _name, const QString& _file, int _type = Code); + ExternalResource(const QString& _name, const QString& _file, int _type = Code); // getters inline QString getName() { return name; } diff --git a/ExternalSource.cpp b/ExternalSource.cpp deleted file mode 100644 index b0f8b32..0000000 --- a/ExternalSource.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "ExternalSource.h" - - -ExternalSource::ExternalSource(const QString& _name, const QString& _file, int _type) { - - name = _name; - file = _file; - type = _type; -} diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 3ea8253..449e2ec 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -1315,9 +1315,23 @@ int FunctionalBlock::createTriggers() { return triggers.size(); } +QList FunctionalBlock::getExternalResources() { + + BlockImplementation* impl = reference->getImplementations().at(0); // for now only take first impl available + QList list = impl->getResources(); + foreach(QString s, list) { + cout << qPrintable(s) << " "; + } + cout << endl; + + return list; +} + + void FunctionalBlock::generateVHDL(const QString& path) throw(Exception){ - BlockImplementation* impl = reference->getImplementations().at(0); // for now only take first impl available + BlockImplementation* impl = reference->getImplementations().at(0); // for now only take first impl available + QFile implFile(impl->getXmlFile()); // reading in into QDomDocument @@ -1445,7 +1459,7 @@ void FunctionalBlock::generateLibraries(QTextStream& out, QDomElement &elt) thro QDomElement eltPack = nodePack.toElement(); QString namePack = eltPack.attribute("name","none"); QString usePack = eltPack.attribute("use","none"); - out << "use " << nameLib << "." << namePack << "." << usePack << endl; + out << "use " << nameLib << "." << namePack << "." << usePack << ";" << endl; } out << endl; } @@ -1485,106 +1499,82 @@ void FunctionalBlock::generateEntityOrComponentBody(QTextStream& out, int indent out << indent << " port (" << endl; + QString ports = ""; + QTextStream outPorts(&ports); + // Generation of the clk & rst signals - out << indent << " -- clk/rst" << endl; + outPorts << indent << " -- clk/rst" << endl; foreach(AbstractInterface* iface, listInputs) { if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) { - out << indent << " " << iface->getName() << " : in std_logic;" << endl; + outPorts << indent << " " << iface->getName() << " : in std_logic;" << endl; } } foreach(AbstractInterface* iface, listOutputs) { if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) { - out << indent << " " << iface->getName() << " : out std_logic;" << endl; + outPorts << indent << " " << iface->getName() << " : out std_logic;" << endl; } } if (hasController) { // Generation of the wishbone signals - out << indent << " -- registers r/w via wishbone" << endl; + outPorts << indent << " -- registers r/w via wishbone" << endl; QList listWB = reference->getWishboneParameters(); for(i=0;itoVHDL(BlockParameter::Entity, 0) << endl; + outPorts << indent << " " << listWB.at(i)->toVHDL(BlockParameter::Entity, 0) << endl; } - out << indent << " " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; + outPorts << indent << " " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; } - - int count = 0; - foreach(AbstractInterface* iface, getInterfaces()) { - if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++; - } // Generation of the data/control signals - int flag = 0; - bool first = true; - - foreach(AbstractInterface* iface, listInputs) { - if(iface->getPurpose() == AbstractInterface::Data) { - if (first) { - out << indent << " -- input data ports" << endl; - first = false; - } - count--; - if (count == 0) flag = AbstractInterface::NoComma; - out << indent << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + QList listIface = getInterfaces(AbstractInterface::Input, AbstractInterface::Data); + if (listIface.size()>0) { + outPorts << indent << " -- input data ports" << endl; + foreach(AbstractInterface* iface, listIface) { + outPorts << indent << " " << iface->toVHDL(AbstractInterface::Entity, 0) << endl; } } - first = true; - foreach(AbstractInterface* iface, listInputs) { - if(iface->getPurpose() == AbstractInterface::Control) { - if (first) { - out << indent << " -- input control ports" << endl; - first = false; - } - count--; - if (count == 0) flag = AbstractInterface::NoComma; - out << indent << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + listIface = getInterfaces(AbstractInterface::Input, AbstractInterface::Control); + if (listIface.size()>0) { + outPorts << indent << " -- input control ports" << endl; + foreach(AbstractInterface* iface, listIface) { + outPorts << indent << " " << iface->toVHDL(AbstractInterface::Entity, 0) << endl; } } - first = true; - foreach(AbstractInterface* iface, listOutputs) { - if(iface->getPurpose() == AbstractInterface::Data) { - if (first) { - out << indent << " -- output data ports" << endl; - first = false; - } - count--; - if (count == 0) flag = AbstractInterface::NoComma; - out << indent << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + listIface = getInterfaces(AbstractInterface::Output, AbstractInterface::Data); + if (listIface.size()>0) { + outPorts << indent << " -- output data ports" << endl; + foreach(AbstractInterface* iface, listIface) { + outPorts << indent << " " << iface->toVHDL(AbstractInterface::Entity, 0) << endl; } } - first = true; - foreach(AbstractInterface* iface, listOutputs) { - if(iface->getPurpose() == AbstractInterface::Control) { - if (first) { - out << indent << " -- output control ports" << endl; - first = false; - } - count--; - if (count == 0) flag = AbstractInterface::NoComma; - out << indent << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + listIface = getInterfaces(AbstractInterface::Output, AbstractInterface::Control); + if (listIface.size()>0) { + outPorts << indent << " -- output control ports" << endl; + foreach(AbstractInterface* iface, listIface) { + outPorts << indent << " " << iface->toVHDL(AbstractInterface::Entity, 0) << endl; } } - first = true; - foreach(AbstractInterface* iface, listBidirs) { - if(iface->getPurpose() == AbstractInterface::Data) { - if (first) { - out << indent << " -- bidirs data ports" << endl; - first = false; - } - count--; - if (count == 0) flag = AbstractInterface::NoComma; - out << indent << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + listIface = getInterfaces(AbstractInterface::InOut, AbstractInterface::Data); + if (listIface.size()>0) { + outPorts << indent << " -- bidirs data ports" << endl; + foreach(AbstractInterface* iface, listIface) { + outPorts << indent << " " << iface->toVHDL(AbstractInterface::Entity, 0) << endl; } } + + ports.chop(2); + ports += "\n"; + out << ports; out << indent << " );" << endl << endl; } void FunctionalBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) { + QRegularExpression rxPort("@\\{([a-zA-Z0-9_]+)\\}"); QString expr; QString code = elt.text(); - cout << qPrintable(code) << endl; + //cout << qPrintable(code) << endl; out << "architecture rtl of " << name << " is" << endl; QStringList listLine = code.split("\n"); @@ -1610,12 +1600,72 @@ void FunctionalBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) } */ if(line.contains("@{")) { - out << line << endl; + QMap modifs; + //cout << qPrintable(line) << endl; + QRegularExpressionMatchIterator matchPort = rxPort.globalMatch(line); + while(matchPort.hasNext()) { + QRegularExpressionMatch m = matchPort.next(); + QString refName = m.captured(1); + AbstractInterface* refIface = reference->getIfaceFromName(refName); + QString funName = getIfaceUserName(refIface); + if (!funName.isEmpty()) { + modifs.insert(m.captured(0),funName); + //cout << "replace " << qPrintable(refIface->getName()) << " by " << qPrintable(funIface->getName()) << endl; + } + } + QMapIterator iterM(modifs); + while(iterM.hasNext()) { + iterM.next(); + QString oldName = iterM.key(); + QString newName = iterM.value(); + line.replace(oldName,newName); + } } + out << line << endl; } + + out << "end rtl;" << endl; } void FunctionalBlock::generateController(QTextStream &out) throw(Exception) { } +QString FunctionalBlock::getIfaceUserName(AbstractInterface* refIface) { + + if (! refIface->isReferenceInterface()) return ""; + + AbstractInterface* funcIface = NULL; + + if (refIface->getDirection() == AbstractInterface::Input) { + foreach(AbstractInterface* iface, getInputs()) { + FunctionalInterface* fi = AI_TO_FUN(iface); + if (fi->getReference() == refIface) { + funcIface = iface; + break; + } + } + } + else if (refIface->getDirection() == AbstractInterface::Output) { + foreach(AbstractInterface* iface, getOutputs()) { + FunctionalInterface* fi = AI_TO_FUN(iface); + if (fi->getReference() == refIface) { + funcIface = iface; + break; + } + } + } + else if (refIface->getDirection() == AbstractInterface::InOut) { + foreach(AbstractInterface* iface, getBidirs()) { + FunctionalInterface* fi = AI_TO_FUN(iface); + if (fi->getReference() == refIface) { + funcIface = iface; + break; + } + } + } + if (funcIface == NULL) return ""; + + return funcIface->getName(); +} + diff --git a/FunctionalBlock.h b/FunctionalBlock.h index 7bba2c8..99f8a80 100644 --- a/FunctionalBlock.h +++ b/FunctionalBlock.h @@ -51,7 +51,10 @@ public: // others void populate(); // create parameters and interface from reference block + + QList getExternalResources(); void generateVHDL(const QString& path) throw(Exception); // main entry to generate the VHDL code + QString getIfaceUserName(AbstractInterface* refIface); // get iface name from reference interface void parametersValidation(QList *checkedBlocks, QList* blocksToConfigure); diff --git a/Graph.cpp b/Graph.cpp index 5b491b0..46159ff 100644 --- a/Graph.cpp +++ b/Graph.cpp @@ -201,3 +201,8 @@ void Graph::generateVHDL(const QString &path) throw(Exception) { throw(e); } } + +QList Graph::getExternalResources() { + QList list = topGroup->getExternalResources(); + return list; +} diff --git a/Graph.h b/Graph.h index e7ff3e2..8b2015f 100644 --- a/Graph.h +++ b/Graph.h @@ -45,6 +45,8 @@ public: // others QList getOutsideInterfaces(); + QList getExternalResources(); // returns the list of all external files needed for VHDL generation + /*! * \brief createPatterns * createPatterns() crosses the graph and for each functional block, it computes diff --git a/GroupBlock.cpp b/GroupBlock.cpp index 66268b9..5b4f34e 100644 --- a/GroupBlock.cpp +++ b/GroupBlock.cpp @@ -6,6 +6,7 @@ #include "string.h" #include #include "Parameters.h" +#include "DelayInputModifier.h" int GroupBlock::counter = 1; @@ -276,11 +277,20 @@ void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) { } } +QList GroupBlock::getExternalResources() { + + QList list; + foreach(AbstractBlock* block, blocks) { + list.append(block->getExternalResources()); + } + return list; +} + void GroupBlock::generateVHDL(const QString& path) throw(Exception) { QString coreFile = ""; - coreFile = path; + coreFile = path; coreFile.append(Parameters::normalizeName(name)); coreFile.append(".vhd"); @@ -299,6 +309,10 @@ void GroupBlock::generateVHDL(const QString& path) throw(Exception) { generateLibraries(outCore,dummyElt); generateEntity(outCore); generateArchitecture(outCore,dummyElt); + + foreach(AbstractBlock* block, blocks) { + block->generateVHDL(path); + } } catch(Exception err) { throw(err); @@ -429,6 +443,38 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( out << "architecture rtl of " << name << " is " << endl << endl; + // generate type for delays, if needed. + QList modWidth; + foreach(AbstractBlock* block, blocks) { + QList listCtlInputs = block->getControlInputs(); + foreach(AbstractInterface* iface, listCtlInputs) { + ConnectedInterface* connCtlIface = AI_TO_CON(iface); + AbstractInputModifier* modifier = connCtlIface->getInputModifier(); + if (modifier != NULL) { + ConnectedInterface* connIface = AI_TO_CON(connCtlIface->getAssociatedIface()); + int w = connIface->getWidth(); + if (w == -1) throw(Exception(INVALID_VALUE)); + if (!modWidth.contains(w)) { + modWidth.append(w); + } + } + } + } + if (modWidth.size() > 0) { + + out << " -- types for modified inputs" << endl; + out << " type vector_of_std_logic is array (natural range <>) of std_logic;" << endl; + foreach(int w, modWidth) { + QString mw = ""; + mw.setNum(w); + QString mwm1 = ""; + mwm1.setNum(w-1); + out << " type vector_of_std_logic_vector"<< mw << " is array (natural range <>) of std_logic_vector(" << mwm1 << " downto 0);" << endl; + } + out << endl; + } + + // generate the components foreach(AbstractBlock* block, blocks) { try { @@ -442,10 +488,10 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( out << endl; // generate signals out << " ----------------------------" << endl; - out << " SIGNALS" << endl; + out << " -- SIGNALS" << endl; out << " ----------------------------" << endl << endl; - +// "normal" signals foreach(AbstractBlock* block, blocks) { try { out << " -- signals from output ports of " << block->getName() << endl; @@ -466,12 +512,24 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( } out << endl; } + + // signal for modifiers foreach(AbstractBlock* block, blocks) { - try { - out << " -- signals for modified input ports of " << block->getName() << endl; - QList listInputs = block->getInputs(); - foreach(AbstractInterface* iface, listInputs) { - if (iface->getPurpose() == AbstractInterface::Control) { + bool hasModif = false; + QList listCtlInputs = block->getControlInputs(); + + foreach(AbstractInterface* iface, listCtlInputs) { + ConnectedInterface* connCtlIface = AI_TO_CON(iface); + AbstractInputModifier* modifier = connCtlIface->getInputModifier(); + if (modifier != NULL) { + hasModif = true; + break; + } + } + if (hasModif) { + try { + out << " -- signals for modified input ports of " << block->getName() << endl; + foreach(AbstractInterface* iface, listCtlInputs) { ConnectedInterface* connCtlIface = AI_TO_CON(iface); AbstractInputModifier* modifier = connCtlIface->getInputModifier(); if (modifier != NULL) { @@ -479,11 +537,11 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( } } } + catch(Exception e) { + throw(e); + } + out << endl; } - catch(Exception e) { - throw(e); - } - out << endl; } out << "begin" << endl; diff --git a/GroupBlock.h b/GroupBlock.h index 23a8ce2..c3b6f9c 100644 --- a/GroupBlock.h +++ b/GroupBlock.h @@ -46,6 +46,7 @@ public: void computeOutputPattern(int nbExec = -1) throw(Exception); void computeAdmittanceDelays() throw(Exception); + QList getExternalResources(); void generateVHDL(const QString& path) throw(Exception); // main entry to generate the VHDL code private: diff --git a/MainWindow.cpp b/MainWindow.cpp index 212e54d..166dfa2 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -451,28 +451,8 @@ void MainWindow::slotGraphAnalysis() { void MainWindow::slotGenerateVHDL() { - QDir baseDir(params->projectPath); - if (!baseDir.exists()) { - cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl; - return; - } - if (! baseDir.exists("src")) { - baseDir.mkdir("src"); - } - if (! baseDir.exists("testbench")) { - baseDir.mkdir("testbench"); - } - if (! baseDir.exists("Makefile")) { - QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim"); - QString dest = params->projectPath; - dest += "/Makefile"; - make.copy(dest); - } - - QString dest = params->projectPath; - dest += "/src/"; try { - params->getGraph()->generateVHDL(dest); + dispatcher->generateVHDL(); } catch(Exception e) { cerr << qPrintable(e.getMessage()) << endl; diff --git a/Makefile-isim b/Makefile-isim index c10eb1d..15319a1 100644 --- a/Makefile-isim +++ b/Makefile-isim @@ -8,16 +8,16 @@ ISIM_LIB := work all : project compile -project : $(PROJECT).prj +project : $(PROJECT_NAME).prj -compile : $(PROJECT).prj $(VHDL_SRC) +compile : $(PROJECT_NAME).prj $(VHDL_SRC) tb_name=$$( echo $(TB_SRC) | sed 's,.*/,,' | sed 's,[.].*,,'); \ - fuse $(ISIM_LIB).$$tb_name $(ISIM_LIB).glbl -prj $(PROJECT).prj -L unisim -L secureip -timeprecision_vhdl ps -o $(SIMU_EXE) + fuse $(ISIM_LIB).$$tb_name $(ISIM_LIB).glbl -prj $(PROJECT_NAME).prj -L unisim -L secureip -timeprecision_vhdl ps -o $(SIMU_EXE) view : $(SIMU_EXE) -gui -wdb $(SIMU_EXE).wdb -$(PROJECT).prj : +$(PROJECT_NAME).prj : if [ -f $@ ]; then rm $@; fi echo "### VHDL sources" for fich in $(VHDL_SRC); do echo vhdl $(ISIM_LIB) $$fich >> $@; done @@ -28,6 +28,6 @@ $(PROJECT).prj : clean : rm -f *~ - rm -f $(PROJECT).prj + rm -f $(PROJECT_NAME).prj cd $(SRC_DIR); rm -f *~ cd $(TB_DIR); rm -f *~ diff --git a/Parameters.cpp b/Parameters.cpp index 32bec53..2ee6255 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -836,7 +836,7 @@ void Parameters::loadImplementationsFromXml() throw(Exception) { if (compList != "none") { QStringList compos = compList.split(","); foreach(QString s, compos) { - impl->addSource(s); + impl->addResource(s); } } @@ -960,7 +960,7 @@ void Parameters::loadSources() throw(Exception) { QString netName = list.at(j); netName.truncate(list.at(j).size() -4); cout << "found netlist " << qPrintable(netName) << endl; - availableSources.append(new ExternalSource(netName,fileName,ExternalSource::Netlist)); + availableResources.append(new ExternalResource(netName,fileName,ExternalResource::Netlist)); } else { cout << "parsing " << qPrintable(fileName) << " ... "; @@ -978,7 +978,7 @@ void Parameters::loadSources() throw(Exception) { if (matchPack.hasMatch()) { QString packName = matchPack.captured(1); cout << "found package " << qPrintable(packName) << endl; - availableSources.append(new ExternalSource(packName,fileName,ExternalSource::Package)); + availableResources.append(new ExternalResource(packName,fileName,ExternalResource::Package)); } } else if (line.contains("entity", Qt::CaseInsensitive)) { @@ -987,7 +987,7 @@ void Parameters::loadSources() throw(Exception) { if (matchEnt.hasMatch()) { QString entityName = matchEnt.captured(1); cout << "found entity " << qPrintable(entityName) << endl; - availableSources.append(new ExternalSource(entityName,fileName,ExternalSource::Code)); + availableResources.append(new ExternalResource(entityName,fileName,ExternalResource::Code)); } } line = in.readLine(); @@ -999,11 +999,14 @@ void Parameters::loadSources() throw(Exception) { } } -ExternalSource* Parameters::searchSourceByName(const QString& name) { - foreach(ExternalSource* s, availableSources) { - if (s->getName() == name) return s; +QList Parameters::searchResourceByName(const QString& name) { + QList listRes; + foreach(ExternalResource* s, availableResources) { + if (s->getName() == name) { + listRes.append(s); + } } - return NULL; + return listRes; } void Parameters::addAvailableBlock(ReferenceBlock *block) { diff --git a/Parameters.h b/Parameters.h index 0329130..9b4ee1b 100644 --- a/Parameters.h +++ b/Parameters.h @@ -24,7 +24,7 @@ class Graph; class GroupWidget; #include "BlockImplementation.h" -#include "ExternalSource.h" +#include "ExternalResource.h" #include "Exception.h" class Exception; @@ -83,7 +83,7 @@ public : // others static QString normalizeName(const QString& name); - ExternalSource* searchSourceByName(const QString& name); + QList searchResourceByName(const QString& name); /*************************************************** attributes that are general to the application @@ -94,7 +94,7 @@ public : QList sourcePathes; QList availableBlocks; QList availableImplementations; - QList availableSources; + QList availableResources; ReferenceBlock* delayRef; BlockImplementation* delayImpl; diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp index 9d6eb53..e0edd96 100644 --- a/ReferenceBlock.cpp +++ b/ReferenceBlock.cpp @@ -660,3 +660,8 @@ void ReferenceBlock::generateEntityOrComponentBody(QTextStream &out, int indentL throw(Exception(INVALID_REFBLOCK_USE)); } +QList ReferenceBlock::getExternalResources() { + QList list; + return list; +} + diff --git a/ReferenceBlock.h b/ReferenceBlock.h index 5dfcbd1..83f38c5 100644 --- a/ReferenceBlock.h +++ b/ReferenceBlock.h @@ -44,6 +44,7 @@ public: void load(QDomElement &elt) throw(Exception); void setHashMd5(); + QList getExternalResources(); void generateVHDL(const QString& path) throw(Exception); // main entry to generate the VHDL code void parametersValidation(QList* checkedBlocks, QList* blocksToConfigure); diff --git a/blast.creator.user b/blast.creator.user index 3d17b3d..3230c1f 100644 --- a/blast.creator.user +++ b/blast.creator.user @@ -1,10 +1,10 @@ - + EnvironmentId - {c8006d66-d34f-42be-ad10-d0207752286d} + {3701e197-5b6c-48ea-9e98-a6cf6de18672} ProjectExplorer.Project.ActiveTarget @@ -61,7 +61,7 @@ Desktop Desktop - {2c9bf876-3476-44eb-8065-1f0844704dda} + {ed04208c-8774-456b-99b9-4a02094ca7a4} 0 0 0 diff --git a/blast.files b/blast.files index 01b85e5..01d93d0 100755 --- a/blast.files +++ b/blast.files @@ -1,5 +1,5 @@ -ExternalSource.h -ExternalSource.cpp +ExternalResource.cpp +ExternalResource.h CustomDialog.h CustomDialog.cpp NewProjectDialog.h diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf index cba0a1d..96b752c 100644 Binary files a/lib/implementations/impls.bmf and b/lib/implementations/impls.bmf differ diff --git a/object-files.txt b/object-files.txt index 3ced8a9..13f2ff6 100644 --- a/object-files.txt +++ b/object-files.txt @@ -10,7 +10,7 @@ COMMON-OBJ = $(BUILDPATH)/AbstractBlock.o \ $(BUILDPATH)/AbstractInputModifier.o \ $(BUILDPATH)/DelayInputModifier.o \ $(BUILDPATH)/BlockImplementation.o \ - $(BUILDPATH)/ExternalSource.o \ + $(BUILDPATH)/ExternalResource.o \ $(BUILDPATH)/Graph.o \ $(BUILDPATH)/AbstractBoxItem.o \ $(BUILDPATH)/BoxItem.o \