From e9f53048b4a0192d95382277e8f40e850998b256 Mon Sep 17 00:00:00 2001 From: sdomas Date: Mon, 5 Mar 2018 12:13:49 +0100 Subject: [PATCH 1/1] moved generate vhdl methods --- AbstractBlock.h | 8 ++ BlockImplementation.cpp | 6 +- BlockImplementation.h | 6 +- FunctionalBlock.cpp | 19 ++++ FunctionalBlock.h | 7 ++ GroupBlock.cpp | 6 +- GroupBlock.h | 9 +- ReferenceBlock.cpp | 27 ++++- ReferenceBlock.h | 16 +-- blast.creator.user | 198 ++++++++++++++++++++++++++++++++++ lib/implementations/impls.bmf | Bin 0 -> 5790 bytes lib/references/references.bmf | Bin 0 -> 21156 bytes 12 files changed, 282 insertions(+), 20 deletions(-) create mode 100644 blast.creator.user create mode 100644 lib/implementations/impls.bmf create mode 100644 lib/references/references.bmf diff --git a/AbstractBlock.h b/AbstractBlock.h index 3e811e9..37cd35a 100644 --- a/AbstractBlock.h +++ b/AbstractBlock.h @@ -4,6 +4,7 @@ #include #include +#include #include "AbstractInterface.h" class AbstractInterface; @@ -58,6 +59,8 @@ public: // others void connectClkReset() throw(Exception); + virtual void generateVHDL(const QString& path) throw(Exception) = 0; // main entry to generate the VHDL code + virtual void parametersValidation(QList* checkedBlocks, QList* blocksToConfigure) = 0; // ugly but usefull @@ -102,6 +105,11 @@ protected: // NB: only GroupBlock and FunctionalBlock have a real parent, except sources that have no parents AbstractBlock* parent; + virtual void generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) = 0; // generates comments from element + virtual void generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) = 0; // generates libraries from element + virtual void generateEntity(QTextStream& out, bool hasController=false) throw(Exception) = 0; // generate the entity using reference + virtual void generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) = 0; // generate the architecture using element + virtual void generateController(QTextStream& out) throw(Exception) = 0; // generate the wishbone controller of the block }; diff --git a/BlockImplementation.cpp b/BlockImplementation.cpp index 46c9722..1553ebb 100644 --- a/BlockImplementation.cpp +++ b/BlockImplementation.cpp @@ -182,7 +182,7 @@ void BlockImplementation::generateVHDL(FunctionalBlock* _block, const QString &p } // This function generates the comments part of the VHDL document -void BlockImplementation::generateComments(QDomElement &elt, QString coreFile, QTextStream& out) throw(Exception) { +void BlockImplementation::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) { for(int i = 0; i < 50; i++) { out << "--"; @@ -222,7 +222,7 @@ void BlockImplementation::generateComments(QDomElement &elt, QString coreFile, Q } // This function generates the library part of the VHDL document -void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception) { +void BlockImplementation::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) { QDomNodeList listLib = elt.elementsByTagName("library"); for(int i = 0; i < listLib.length(); i++) { @@ -370,7 +370,7 @@ void BlockImplementation::generateEntity(QTextStream& out, bool hasController) t } // This function generates the architecture part of the VHDL document -void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception) { +void BlockImplementation::generateArchitecture(QTextStream& out, QDomElement &elt) throw(Exception) { QString expr; QString code = elt.text(); diff --git a/BlockImplementation.h b/BlockImplementation.h index ad50a6a..8bbc297 100644 --- a/BlockImplementation.h +++ b/BlockImplementation.h @@ -70,10 +70,10 @@ private: QHash productionPattern; // key = reference interface name, value = pattern expression QString productionCounter; - void generateComments(QDomElement &elt,QString coreFile, QTextStream& out) throw(Exception); // generates comments from element - void generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception); // generates libraries from element + void generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception); // generates comments from element + void generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception); // generates libraries from element void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference - void generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception); // generate the architecture using element + void generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception); // generate the architecture using element void generateController(QTextStream& out) throw(Exception); // generate the wishbone controller of the block QString getIfaceUserName(AbstractInterface* refIface); // get the name of an interface given by the user, from the reference interface diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 8ecd6a3..b54e4e3 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -1312,3 +1312,22 @@ int FunctionalBlock::createTriggers() { } return triggers.size(); } + +void FunctionalBlock::generateVHDL(const QString& path) throw(Exception){ + } + +void FunctionalBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) { + +} + +void FunctionalBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) { + +} + +void FunctionalBlock::generateEntity(QTextStream& out, bool hasController=false) throw(Exception) { + +} + +void FunctionalBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) { + +} diff --git a/FunctionalBlock.h b/FunctionalBlock.h index c51ff77..d3bd581 100644 --- a/FunctionalBlock.h +++ b/FunctionalBlock.h @@ -51,6 +51,7 @@ public: // others void populate(); // create parameters and interface from reference block + void generateVHDL(const QString& path) throw(Exception); // main entry to generate the VHDL code void parametersValidation(QList *checkedBlocks, QList* blocksToConfigure); QString getReferenceXmlFile(); @@ -153,6 +154,12 @@ private: */ void shiftRightPattern(const QMap* >& pattern, int offset); + void generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception); // generates comments from element + void generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception); // generates libraries from element + void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference + void generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception); // generate the architecture using element + void generateController(QTextStream& out) throw(Exception); // generate the wishbone controller of the block + QMap* > consumptionPattern; QMap admittanceCyclic; // the admittance expressed as prologue-cyclic part-epilogue, deduced from admittance QMap* > admittance; // the admittance taking into account nb exec. diff --git a/GroupBlock.cpp b/GroupBlock.cpp index 6cd76b9..a3966bd 100644 --- a/GroupBlock.cpp +++ b/GroupBlock.cpp @@ -295,11 +295,11 @@ void GroupBlock::generateVHDL(const QString& path) throw(Exception) { } -void GroupBlock::generateComments(QTextStream& out) throw(Exception) { +void GroupBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) { out << " -- VHDL generated automatically for " << name << " --" << endl << endl; } -void GroupBlock::generateLibraries(QTextStream& out) throw(Exception) { +void GroupBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) { out << "library IEEE;" << endl; out << "use IEEE.STD_LOGIC_1164.all;" << endl; @@ -410,7 +410,7 @@ void GroupBlock::generateEntity(QTextStream& out) throw(Exception) { } -void GroupBlock::generateArchitecture(QTextStream& out) throw(Exception) { +void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(Exception) { } diff --git a/GroupBlock.h b/GroupBlock.h index 172803d..bb5e771 100644 --- a/GroupBlock.h +++ b/GroupBlock.h @@ -64,11 +64,12 @@ private: * found by taking the output pattern of the connectedFrom interface. */ void createInputPattern(); - void generateComments(QTextStream& out) throw(Exception); - void generateLibraries(QTextStream& out) throw(Exception); - void generateEntity(QTextStream& out) throw(Exception); - void generateArchitecture(QTextStream& out) throw(Exception); + void generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception); // generates comments from element + void generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception); // generates libraries from element + void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference + void generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception); // generate the architecture using element + void generateController(QTextStream& out) throw(Exception); // generate the wishbone controller of the block bool topGroup; QList blocks; // contains instances of FunctionalBlock or GroupBlock that are children of this group diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp index 5137d73..f6fd9c7 100644 --- a/ReferenceBlock.cpp +++ b/ReferenceBlock.cpp @@ -6,6 +6,7 @@ #include "BlockParameterGeneric.h" #include "BlockParameterPort.h" #include "BlockParameterWishbone.h" +#include "Parameters.h" ReferenceBlock::ReferenceBlock(const QString _xmlFile) : AbstractBlock() { xmlFile = _xmlFile; @@ -94,7 +95,7 @@ void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) { } else { QDomText txtName = nodeNameTxt.toText(); - name = normalizeName(txtName.data().trimmed()); + name = Parameters::normalizeName(txtName.data().trimmed()); cout<< "block name : " << qPrintable(name) << endl; } @@ -635,3 +636,27 @@ void ReferenceBlock::computeAdmittanceDelays() throw(Exception) { } +void ReferenceBlock::generateVHDL(const QString& path) throw(Exception){ + throw(Exception(INVALID_REFBLOCK_USE)); +} + +void ReferenceBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) { + throw(Exception(INVALID_REFBLOCK_USE)); +} + +void ReferenceBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) { + throw(Exception(INVALID_REFBLOCK_USE)); +} + +void ReferenceBlock::generateEntity(QTextStream& out, bool hasController=false) throw(Exception) { + throw(Exception(INVALID_REFBLOCK_USE)); +} + +void ReferenceBlock::generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception) { + throw(Exception(INVALID_REFBLOCK_USE)); +} + +void ReferenceBlock::generateController(QTextStream& out) throw(Exception) { + throw(Exception(INVALID_REFBLOCK_USE)); +} + diff --git a/ReferenceBlock.h b/ReferenceBlock.h index baa8aaf..79db803 100644 --- a/ReferenceBlock.h +++ b/ReferenceBlock.h @@ -44,6 +44,10 @@ public: void load(QDomElement &elt) throw(Exception); void setHashMd5(); + void generateVHDL(const QString& path) throw(Exception); // main entry to generate the VHDL code + + void parametersValidation(QList* checkedBlocks, QList* blocksToConfigure); + private: QString xmlFile; // the xml file from which attributes are initialized. QString hashMd5; @@ -61,16 +65,16 @@ private: friend QDataStream &operator<<(QDataStream &out, const ReferenceBlock &b); friend QDataStream &operator>>(QDataStream &in, ReferenceBlock &b); - - // AbstractBlock interface -public: - void parametersValidation(QList* checkedBlocks, QList* blocksToConfigure); - -private: // patterns void checkInputPatternCompatibility() throw(Exception); void computeOutputPattern(int nbExec = -1) throw(Exception); void computeAdmittanceDelays() throw(Exception); + + void generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception); // generates comments from element + void generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception); // generates libraries from element + void generateEntity(QTextStream& out, bool hasController=false) throw(Exception); // generate the entity using reference + void generateArchitecture(QTextStream& out, QDomElement &elt ) throw(Exception); // generate the architecture using element + void generateController(QTextStream& out) throw(Exception); // generate the wishbone controller of the block }; #endif // __REFERENCEBLOCK_H__ diff --git a/blast.creator.user b/blast.creator.user new file mode 100644 index 0000000..37faf88 --- /dev/null +++ b/blast.creator.user @@ -0,0 +1,198 @@ + + + + + + EnvironmentId + {94112477-caab-4897-8f75-5f412f2c883a} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {c934e180-ebc6-41ed-be82-502cc94f41f6} + 0 + 0 + 0 + + /home/sdomas/Projet/Blast/code/blast + + + + all + + false + + + true + Make + + GenericProjectManager.GenericMakeStep + + 1 + Compiler + + ProjectExplorer.BuildSteps.Build + + + + + clean + + true + + + true + Make + + GenericProjectManager.GenericMakeStep + + 1 + Nettoyer + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Défaut + Défaut + GenericProjectManager.GenericBuildConfiguration + + 1 + + + 0 + Déploiement + + ProjectExplorer.BuildSteps.Deploy + + 1 + Déployer localement + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf new file mode 100644 index 0000000000000000000000000000000000000000..b69078a4664468635a51c6942ba6b7fc55fb2126 GIT binary patch literal 5790 zcmd6r&2AG{6vxk)3RNr+MbQXZD2u2|6jt-7jY#j#0Djh)&q2_Q>( z0v0S-u;`-dx=+Be%RWXQq`z~Iujk(RZ~_R1u_l?Bd(OG%{Lkl%NcvVpzTy0j^G~@c z2QrqY(&uU_J$Jp!)lJ!v33pFenQ`|}hN92)dXMKl$I%U*4rL%+RtHEsTzMaE$}5 zt8&Zzs(9PTY|H(E+!njt=bX!SVNDt*?D|IyKIjs4$3)wJIGQ~7E98`53g&8 z!98N2PtE*w5r3+s*2gTOQdUEnYz392fwwGz(kRoz7&4j$bj?6khiH!D;w$1prCkXm zRneHtf1!R;3u;3Uo4Agn^;4}aBB$2o>02#F-P0s*E%U0XgEkj+vdHHvaL5^U(Wc8YtHCk1a$07+oAieKl_IHr<1784`tl*F1iWVrld-mX9iDuB@Nv9IH5AUopulI2!L4-Rv7;zQYcNy4N?Gj6LSQ zbNQX->=n*=;nb|2xJcdC$PXvmPqB->RekDRte-x?sygCoh<*EH<) zCm#=4ceOfid**xKg+*Vr&T3uo7qI%fhPkBN_UB|=ms9K59Ww4mzN?jW#dZaDW&9t9 zWm7_#c|u21T#n&b)tGUY1(k}|B`*P9en?*iH N4X@L_O1wwK{vTwo#pwV5 literal 0 HcmV?d00001 diff --git a/lib/references/references.bmf b/lib/references/references.bmf new file mode 100644 index 0000000000000000000000000000000000000000..a34f5925c214b924674d852699a77d62c20aedb5 GIT binary patch literal 21156 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 literal 0 HcmV?d00001 -- 2.39.5