From: stephane Domas Date: Sun, 14 Jan 2018 23:02:16 +0000 (+0100) Subject: add graph modif, progress on vhdl generation X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain/4cf57e6db08da791233d75237f62e74bc88dd427?ds=sidebyside;hp=--cc add graph modif, progress on vhdl generation --- 4cf57e6db08da791233d75237f62e74bc88dd427 diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp index 66c8f37..f551b30 100644 --- a/AbstractBlock.cpp +++ b/AbstractBlock.cpp @@ -234,3 +234,4 @@ QList AbstractBlock::getWishboneParameters() { } return lst; } + diff --git a/AbstractBlock.h b/AbstractBlock.h index 2bb2717..80e0413 100644 --- a/AbstractBlock.h +++ b/AbstractBlock.h @@ -37,11 +37,14 @@ public: QList getWishboneParameters(); inline AbstractBlock* getParent() { return parent; } inline bool getPatternComputed() { return patternComputed; } + inline int getTraversalLevel() { return traversalLevel; } // setters void setName(const QString& str); virtual void setParent(AbstractBlock* _parent); inline void setPatternComputed(bool state) { patternComputed = state; } + inline void resetTraversalLevel() { traversalLevel = -1; } + inline void setTraversalLevel(int level) { traversalLevel = level; } // testers virtual bool isReferenceBlock(); @@ -72,6 +75,7 @@ public: // patterns virtual void checkInputPatternCompatibility() throw(Exception) = 0; virtual void computeOutputPattern(int nbExec = -1) throw(Exception) = 0; + virtual void computeAdmittanceDelays() throw(Exception) = 0; protected: @@ -90,6 +94,7 @@ protected: // patterns bool patternComputed; + int traversalLevel; // the level (0, 1, ...) during the traversal of the graph // NB: only GroupBlock and FunctionalBlock have a real parent, except sources that have no parents AbstractBlock* parent; diff --git a/AbstractInputModifier.cpp b/AbstractInputModifier.cpp new file mode 100644 index 0000000..aa9c9a2 --- /dev/null +++ b/AbstractInputModifier.cpp @@ -0,0 +1,28 @@ +#include "AbstractInputModifier.h" + +AbstractInputModifier::AbstractInputModifier() { + + pattern = new QList(); +} + +AbstractInputModifier::~AbstractInputModifier() { + + delete pattern; +} + +bool AbstractInputModifier::isDelay() { + return false; +} + +bool AbstractInputModifier::isComplexDelay() { + return false; +} + +bool AbstractInputModifier::isFIFO() { + return false; +} + +bool AbstractInputModifier::isDecimator() { + return false; +} + diff --git a/AbstractInputModifier.h b/AbstractInputModifier.h new file mode 100644 index 0000000..bbc5bdd --- /dev/null +++ b/AbstractInputModifier.h @@ -0,0 +1,37 @@ +#ifndef __ABSTRACTINPUTMODIFIER_H__ +#define __ABSTRACTINPUTMODIFIER_H__ + +#include + +#include + +using namespace std; +using namespace Qt; + +class AbstractInputModifier { + +public: + + AbstractInputModifier(); + virtual ~AbstractInputModifier(); + + //getters + virtual QString getTypeStr() = 0; + virtual QString getParametersStr() = 0; + + // setters + + // testers + virtual bool isDelay(); + virtual bool isComplexDelay(); + virtual bool isFIFO(); + virtual bool isDecimator(); + + // others + virtual QList* getModifiedInput(QList* input) = 0; + + protected: + QList* pattern; // the pattern modified by this +}; + +#endif // __ABSTRACTINPUTMODIFIER_H__ diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp index 76654ff..c03cba9 100644 --- a/AbstractInterface.cpp +++ b/AbstractInterface.cpp @@ -209,15 +209,21 @@ int AbstractInterface::typeFromString(const QString &_type) { QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { + if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE)); QString msb = width; QString ret=""; bool ok; + cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(msb) << " with type = " << qPrintable(getTypeString()) << endl; + if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) { QString formatBool = "%1 : %2 std_logic"; - QString formatVector = "%1 : %2 std_logic_vector(%3 downto %4)"; + QString formatVector = ""; + if (endianess == LittleEndian) formatVector = "%1 : %2 std_logic_vector(%3 downto %4)"; + else formatVector = "%1 : %2 std_logic_vector(%4 to %3)"; + if ((flags & BlockParameter::NoComma) == 0) { formatBool.append(";"); formatVector.append(";"); @@ -233,7 +239,7 @@ QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { orientation = "inout"; } if (type == Boolean) { - ret = formatVector.arg(name).arg(orientation); + ret = formatBool.arg(name).arg(orientation); } else if (type == Natural) { int w = width.toInt(&ok); @@ -246,6 +252,8 @@ QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { } } else if (type == Expression) { + + /* must check the following conditions : - if it contains user/port parameters : must evaluate their numeric value - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated. @@ -255,7 +263,7 @@ QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { QList listPorts = owner->getPortParameters(); foreach(BlockParameter* p, listUsers) { QString var = "$"; - var.append(p->getName()); + var += p->getName(); if (width.contains(var)) { int w = p->getValue().toInt(&ok); if (!ok) throw(Exception(INVALID_VALUE)); @@ -264,18 +272,21 @@ QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) { } foreach(BlockParameter* p, listPorts) { QString var = "$"; - var.append(p->getName()); + var += p->getName(); + if (width.contains(var)) { + msb.replace(var,p->toVHDL(0,0)); + } + } + foreach(BlockParameter* p, listGenerics) { + QString var = "$"; + var += p->getName(); if (width.contains(var)) { - BlockParameterPort* pp = (BlockParameterPort*)p; - AbstractInterface* iface = owner->getIfaceFromName(pp->getIfaceName()); - - int w = p->getValue().toInt(&ok); - if (!ok) throw(Exception(INVALID_VALUE)); - msb.replace(var,p->getValue().toString()); + msb.replace(var,p->getName()); } } - - ret = formatVector.arg(name).arg(orientation).arg("toto").arg("0"); + msb += "-1"; + cout << "iface size :" << qPrintable(msb) << endl; + ret = formatVector.arg(name).arg(orientation).arg(msb).arg("0"); } } return ret; diff --git a/BlockImplementation.cpp b/BlockImplementation.cpp index b751021..f71297f 100644 --- a/BlockImplementation.cpp +++ b/BlockImplementation.cpp @@ -73,20 +73,31 @@ void BlockImplementation::loadPatterns(QDomElement& root) throw(Exception) { } bool BlockImplementation::checkPatterns() { - if (reference == NULL) return false; + + + if (reference == NULL) { + cout << "no ref. while checking patterns of implementation " << endl; + return false; + } AbstractInterface* iface; QHashIterator iterI(consumptionPattern); while (iterI.hasNext()) { iterI.next(); iface = reference->getIfaceFromName(iterI.key()); - if (iface == NULL) return false; + if (iface == NULL) { + cout << "cannot found an input ref. iface for impl. iface " << qPrintable(iterI.key()) << endl; + return false; + } } QHashIterator iterO(productionPattern); while (iterO.hasNext()) { iterO.next(); iface = reference->getIfaceFromName(iterO.key()); - if (iface == NULL) return false; + if (iface == NULL) { + cout << "cannot found an output ref. iface for impl. iface " << qPrintable(iterI.key()) << endl; + return false; + } } return true; } @@ -215,17 +226,17 @@ void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) for(int i = 0; i < listLib.length(); i++) { QDomNode nodeLib = listLib.item(i); QDomElement eltLib = nodeLib.toElement(); - QString nameLib = eltLib.attribute("name", ""); + QString nameLib = eltLib.attribute("name","none"); out << "library " << nameLib << ";\n"; QDomNodeList listPack = eltLib.elementsByTagName("package"); for(int j = 0; j < listPack.length(); j++) { QDomNode nodePack = listPack.item(j); QDomElement eltPack = nodePack.toElement(); - QString namePack = eltPack.attribute("name", ""); - QString usePack = elt.attribute("use",""); - out << "use " << nameLib << "." << namePack << "." << usePack << ";\n"; + QString namePack = eltPack.attribute("name","none"); + QString usePack = eltPack.attribute("use","none"); + out << "use " << nameLib << "." << namePack << "." << usePack << endl; } - out << "\n"; + out << endl; } } @@ -233,11 +244,11 @@ void BlockImplementation::generateLibraries(QDomElement &elt, QTextStream& out) void BlockImplementation::generateEntity(QTextStream& out, bool hasController) throw(Exception) { int i=0; - nameEnt = reference->getName(); + nameEnt = block->getName(); //QList listParams = reference->getParameters(); - QList listInputs = reference->getInputs(); - QList listOutputs = reference->getOutputs(); - QList listBidirs = reference->getBidirs(); + QList listInputs = block->getInputs(); + QList listOutputs = block->getOutputs(); + QList listBidirs = block->getBidirs(); QString typePort, namePort; out << "entity " << nameEnt << " is\n"; @@ -246,7 +257,7 @@ void BlockImplementation::generateEntity(QTextStream& out, bool hasController) t /* TODO : rewrite the generation to take into acocunt the new object hierarchy */ // Generation of the generics - QList listGenerics = reference->getGenericParameters(); + QList listGenerics = block->getGenericParameters(); if ((!listGenerics.isEmpty()) || (hasController)) { out << " generic (" << endl; if (hasController) { @@ -256,9 +267,9 @@ void BlockImplementation::generateEntity(QTextStream& out, bool hasController) t out << endl; } for(i=0;itoVHDL(BlockParameter::Entity, 0); + out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl; } - out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma); + out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; out << " );" << endl; } @@ -267,9 +278,9 @@ void BlockImplementation::generateEntity(QTextStream& out, bool hasController) t // Generation of the clk & rst signals out << " -- clk/rst" << endl; - for(int i = 0; i < listInputs.size(); i++) { - if(listInputs.at(i)->getPurpose() == AbstractInterface::Clock || listInputs.at(i)->getPurpose() == AbstractInterface::Reset) { - out << " " << listInputs.at(i)->getName() << " : in std_logic;" << endl; + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) { + out << " " << iface->getName() << " : in std_logic;" << endl; } } @@ -278,55 +289,98 @@ void BlockImplementation::generateEntity(QTextStream& out, bool hasController) t out << " -- registers r/w via wishbone" << endl; QList listWB = reference->getWishboneParameters(); for(i=0;itoVHDL(BlockParameter::Entity, 0); + out << " " << listWB.at(i)->toVHDL(BlockParameter::Entity, 0) << endl; } - out << " " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma); + out << " " << listWB.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl; } - // Generation of the data signals - out << "-- data ports\n"; - for(int i = 0; i < listInputs.size(); i++) { - namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listInputs.at(i)->getName())); - if(listInputs.at(i)->getWidth().compare("1")) - typePort = "std_logic"; - else - typePort = calculateWidth(listInputs.at(i)->getWidth()); - if(listInputs.at(i)->getPurpose() == 1) - out << namePort << " : in std_logic_vector(" << typePort << " -1 downto 0) ;\n"; + int count = 0; + foreach(AbstractInterface* iface, block->getInterfaces()) { + if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++; } + // Generation of the data/control signals - for(int i = 0; i < listOutputs.size(); i++) { - namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listOutputs.at(i)->getName())); - if(listOutputs.at(i)->getWidth().compare("1")) - typePort = "std_logic"; - else - typePort = calculateWidth(listOutputs.at(i)->getWidth()); - if(listOutputs.at(i)->getPurpose() == 1) - out << namePort << " : out std_logic_vector(" << typePort << " -1 downto 0) ;\n"; - } + int flag = 0; + bool first = true; - for(int i = 0; i < listBidirs.size(); i++) { - namePort = getIfaceUserName(reference->AbstractBlock::getIfaceFromName(listBidirs.at(i)->getName())); - if(listBidirs.at(i)->getWidth().compare(("1"))) - typePort = "std_logic"; - else - typePort = calculateWidth((listBidirs.at(i)->getWidth())); - if(listBidirs.at(i)->getPurpose() == 1) - out << namePort << " : inout std_logic_vector(" << typePort << " -1 downto 0) ;\n"; + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- input data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listInputs) { + if(iface->getPurpose() == AbstractInterface::Control) { + if (first) { + out << " -- input control ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listOutputs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- output data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listOutputs) { + if(iface->getPurpose() == AbstractInterface::Control) { + if (first) { + out << " -- output control ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } + } + first = true; + foreach(AbstractInterface* iface, listBidirs) { + if(iface->getPurpose() == AbstractInterface::Data) { + if (first) { + out << " -- bidirs data ports" << endl; + first = false; + } + count--; + if (count == 0) flag = AbstractInterface::NoComma; + out << " " << iface->toVHDL(AbstractInterface::Entity, flag) << endl; + } } + out << " );" << endl << endl; + out << "end " << nameEnt << ";" << endl << endl; } // This function generates the architecture part of the VHDL document void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& out) throw(Exception) { QString expr; - QDomElement eltArch = elt.nextSiblingElement("architecture"); - out << "architecture " << nameEnt <<"_1 of " << nameEnt << "is\n"; - QString implText = eltArch.text(); - QStringList listLine = implText.split("\n"); + QString code = elt.text(); + cout << qPrintable(code) << endl; + out << "architecture rtl of " << nameEnt << " is" << endl; + + QStringList listLine = code.split("\n"); for(int i =0; i < listLine.size(); i++) { - if(listLine.at(i).contains(QRegularExpression("@foreach{")) != -1) { + QString line = listLine.at(i).simplified(); + + /* + if(listLine.at(i).contains(QRegularExpression("@foreach{"))) { while(listLine.at(i).compare("@endforeach") != -1) { expr = expr + listLine.at(i) + '\n'; i++; @@ -334,7 +388,7 @@ void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& ou expr = expr + listLine.at(i); out << evalComplex(expr, 1) << '\n'; } - if(listLine.at(i).contains(QRegularExpression("@caseeach{")) != -1) { + if(listLine.at(i).contains(QRegularExpression("@caseeach{"))) { while(listLine.at(i).compare("@endcaseeach") != -1) { expr = expr + listLine.at(i) + '\n'; i++; @@ -342,11 +396,10 @@ void BlockImplementation::generateArchitecture(QDomElement &elt, QTextStream& ou expr = expr + listLine.at(i); out << evalComplex(expr, 2) << '\n'; } - - if(listLine.at(i).contains('@') == -1) - out << listLine.at(i) << "\n"; - else - out << eval(listLine.at(i), out) << "\n"; +*/ + if(line.contains("@{")) { + out << line << endl; + } } } diff --git a/BlockImplementation.h b/BlockImplementation.h index 4866e85..ad50a6a 100644 --- a/BlockImplementation.h +++ b/BlockImplementation.h @@ -37,6 +37,10 @@ public: inline QHash getProductionPattern() { return productionPattern; } inline QString getProductionCounter() { return productionCounter; } // setters + inline void setDelta(QString _delta) { delta = _delta; } + inline void setConsumptionPattern(QHash pattern) { consumptionPattern = pattern; } + inline void setProductionPattern(QHash pattern) { productionPattern = pattern; } + inline void setProductionCounter(QString pattern) { productionCounter = pattern; } QString eval(QString line, QTextStream& out); QString evalComplex(QString line, int num); diff --git a/BlockLibraryTree.cpp b/BlockLibraryTree.cpp index 33980f9..2c9b365 100644 --- a/BlockLibraryTree.cpp +++ b/BlockLibraryTree.cpp @@ -1,8 +1,6 @@ #include "BlockLibraryTree.h" -BlockLibraryTree::BlockLibraryTree() { - tabCategories = NULL; - tabIdParent = NULL; +BlockLibraryTree::BlockLibraryTree() { nbCategories = 0; } @@ -14,8 +12,7 @@ void BlockLibraryTree::clear() { for(int i=0;iblocks.clear(); } } - +/* void BlockLibraryTree::addItem(QXmlAttributes &attributes) { nbCategories++; @@ -51,15 +48,22 @@ void BlockLibraryTree::addItem(QXmlAttributes &attributes) tabCategories[id] = cat; tabIdParent[id] = idParent; } - -bool BlockLibraryTree::initChildParent() -{ +*/ +bool BlockLibraryTree::initChildParent() { // initializing parent/childs + bool ok; for(int i=0;i= nbCategories) return false; - tabCategories[i]->setParent(tabCategories[tabIdParent[i]]); - tabCategories[tabIdParent[i]]->addChild(tabCategories[i]); + if (tabIdParent[i] >= 0) { + ok = false; + foreach (BlockCategory* cat, tabCategories) { + if (cat->getId() == tabIdParent[i]) { + tabCategories[i]->setParent(cat); + cat->addChild(tabCategories[i]); + ok = true; + break; + } + } + if (!ok) return false; } } return true; @@ -79,20 +83,15 @@ void BlockLibraryTree::load(QDomElement &elt) throw(Exception) { if (elt.tagName() != "categories") throw(Exception(CONFIGFILE_CORRUPTED)); - QString nbStr = elt.attribute("nb","none"); bool ok; - int nb = nbStr.toInt(&ok); QDomNodeList list = elt.elementsByTagName("category"); nbCategories = list.size(); - if (nb != nbCategories) throw(Exception(CONFIGFILE_CORRUPTED)); QString name; int id; QString idStr; int idParent; QString idParentStr; - tabCategories = new BlockCategory* [nbCategories]; - tabIdParent = new int[nbCategories]; BlockCategory* cat = NULL; // creating all BlockCategory objects @@ -103,35 +102,31 @@ void BlockLibraryTree::load(QDomElement &elt) throw(Exception) { idStr = e.attribute("id","none"); idParentStr = e.attribute("parent","none"); id = idStr.toInt(&ok); - if ((!ok) || (id < 0) || (id >= nbCategories)) throw(Exception(CONFIGFILE_CORRUPTED)); + if ((!ok) || (id < 0) || (id >= 100)) throw(Exception(CONFIGFILE_CORRUPTED)); idParent = idParentStr.toInt(&ok); - if ((!ok)|| (idParent < -1) || (idParent >= nbCategories)) throw(Exception(CONFIGFILE_CORRUPTED)); + if ((!ok)|| (idParent < -1) || (idParent >= 100)) throw(Exception(CONFIGFILE_CORRUPTED)); cat = new BlockCategory(name,id); - tabCategories[id] = cat; - tabIdParent[id] = idParent; + tabCategories.append(cat); + tabIdParent.append(idParent); } + cat = new BlockCategory("hidden",100); + tabCategories.append(cat); + tabIdParent.append(0); ok = initChildParent(); - delete [] tabIdParent; + if (!ok) throw(Exception(CONFIGFILE_CORRUPTED)); } BlockCategory* BlockLibraryTree::searchCategory(int id) { - if (tabCategories != NULL) { - if ((id>=0) && (id < nbCategories)) { - return tabCategories[id]; - } + foreach(BlockCategory* cat, tabCategories) { + if (cat->getId() == id) return cat; } - return NULL; } BlockCategory *BlockLibraryTree::getRoot() { - if (tabCategories != NULL) { - if (nbCategories > 0) { - return tabCategories[0]; - } - } - return NULL; + + return searchCategory(0); } diff --git a/BlockLibraryTree.h b/BlockLibraryTree.h index f8fa60c..880fd17 100644 --- a/BlockLibraryTree.h +++ b/BlockLibraryTree.h @@ -40,8 +40,8 @@ private: The root of the tree is in fact tabCategories[0] */ - BlockCategory** tabCategories; - int* tabIdParent; + QList tabCategories; + QList tabIdParent; int nbCategories; }; diff --git a/BlockLibraryWidget.cpp b/BlockLibraryWidget.cpp index 544a1d1..0d2636d 100644 --- a/BlockLibraryWidget.cpp +++ b/BlockLibraryWidget.cpp @@ -50,17 +50,20 @@ void BlockLibraryWidget::addChild(BlockCategory *catParent,QTreeWidgetItem* item QList childs = catParent->getAllChilds(); foreach(BlockCategory* cat, childs){ - newItemCat = new QTreeWidgetItem(itemParent); - newItemCat->setData(0,Qt::DisplayRole, cat->getName()); - QList list = cat->getBlocks(); - for(int i=0; isetData(0,Qt::DisplayRole, list.at(i)->getName()); - newItemBlock->setData(1,Qt::DisplayRole, cat->getId()); - newItemBlock->setData(2,Qt::DisplayRole, i); - newItemBlock->setIcon(0,QIcon("icons/window_new.png")); + + if (cat->getId()<100) { + newItemCat = new QTreeWidgetItem(itemParent); + newItemCat->setData(0,Qt::DisplayRole, cat->getName()); + QList list = cat->getBlocks(); + for(int i=0; isetData(0,Qt::DisplayRole, list.at(i)->getName()); + newItemBlock->setData(1,Qt::DisplayRole, cat->getId()); + newItemBlock->setData(2,Qt::DisplayRole, i); + newItemBlock->setIcon(0,QIcon("icons/window_new.png")); + } + addChild(cat,newItemCat); } - addChild(cat,newItemCat); } /* TO DO : - getting the childs of catParent diff --git a/BlockParameter.cpp b/BlockParameter.cpp index 6207148..b4fce09 100644 --- a/BlockParameter.cpp +++ b/BlockParameter.cpp @@ -42,7 +42,7 @@ int BlockParameter::getIntValue(bool* ok) { double BlockParameter::getDoubleValue(bool* ok) { if ((type == Real) || (type == Natural) || (type == Positive) || (type == Integer)) { - *ok = true; + *ok = true; return getValue().toDouble(); } *ok = false; diff --git a/BlockParameter.h b/BlockParameter.h index e8068d4..15df2d8 100644 --- a/BlockParameter.h +++ b/BlockParameter.h @@ -46,7 +46,7 @@ public : virtual QVariant getValue(); // may be overriden int getIntValue(bool* ok); double getDoubleValue(bool* ok); - bool getBooleanValue(bool* ok); + bool getBooleanValue(bool* ok); QString getStringValue(); virtual QString getContext() = 0; diff --git a/BlockParameterGeneric.cpp b/BlockParameterGeneric.cpp index 5b15eb9..5b694fc 100644 --- a/BlockParameterGeneric.cpp +++ b/BlockParameterGeneric.cpp @@ -57,13 +57,13 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { } if (!userValue.isNull()) { - ret = formatValue.arg(name).arg(type).arg(userValue.toString()); + ret = formatValue.arg(name).arg(getTypeString()).arg(userValue.toString()); } else if (!defaultValue.isNull()) { - ret = formatValue.arg(name).arg(type).arg(defaultValue.toString()); + ret = formatValue.arg(name).arg(getTypeString()).arg(defaultValue.toString()); } else { - ret = formatNoValue.arg(name).arg(type); + ret = formatNoValue.arg(name).arg(getTypeString()); } } else if (context == BlockParameter::Architecture) { diff --git a/BoxItem.cpp b/BoxItem.cpp index 53d56ec..34b567a 100644 --- a/BoxItem.cpp +++ b/BoxItem.cpp @@ -514,6 +514,9 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { QAction* showWishboneIface = NULL; QAction* showParameters = NULL; QAction* showPatterns = NULL; + QAction* showModifier = NULL; + QAction* removeModifier = NULL; + QAction* generateVHDL = NULL; InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y()); // menu for interface @@ -560,9 +563,22 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { } } } - if ((iface->getAssociatedIface() != NULL) && (iface->getDirection() == AbstractInterface::Output)) { - showPatterns = menu.addAction("Show patterns"); + if (iface->getAssociatedIface() != NULL) { + if (iface->getDirection() == AbstractInterface::Output) { + showPatterns = menu.addAction("Show output pattern"); + } + else if (iface->getDirection() == AbstractInterface::Input) { + showPatterns = menu.addAction("Show input pattern"); + } + } + + if (iface->getInputModifier() != NULL) { + removeModifier = menu.addAction("Remove input modifier"); + } + if (iface->getInputModifier() != NULL) { + showModifier = menu.addAction("Show input modifier parameters"); } + } // menu for blocks (group or func) else { @@ -588,6 +604,7 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { showWishboneIface->setChecked(wishboneVisible); } removeAction = menu.addAction("Remove"); + generateVHDL = menu.addAction("Generate VHDL"); } QAction* selectedAction = NULL; @@ -643,6 +660,16 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { else if(selectedAction == showPatterns) { dispatcher->showPatterns(ifaceItem); } + else if(selectedAction == removeModifier) { + dispatcher->removeModifier(ifaceItem); + } + else if(selectedAction == showModifier) { + dispatcher->showModifier(ifaceItem); + } + else if(selectedAction == generateVHDL) { + dispatcher->generateBlockVHDL(this); + } + } void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) { @@ -703,6 +730,7 @@ void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) { */ functionalBlock->setName(name); setRefBlock(functionalBlock); + params->blockToItem.insert(functionalBlock,this); setPos(posX,posY); setDimension(dimX,dimY); diff --git a/ConnectedInterface.cpp b/ConnectedInterface.cpp index 017401a..3724417 100644 --- a/ConnectedInterface.cpp +++ b/ConnectedInterface.cpp @@ -7,15 +7,17 @@ ConnectedInterface::ConnectedInterface(AbstractBlock* _owner) : AbstractInterface(_owner) { connectedFrom = NULL; outputPattern = NULL; + inputModifier = NULL; } ConnectedInterface::ConnectedInterface(AbstractBlock* _owner, const QString& _name, int _direction, int _purpose, const QString& _type, const QString& _width) : AbstractInterface(_owner, _name, _direction, _purpose, _type, _width) { - connectedFrom = NULL; + connectedFrom = NULL; outputPattern = NULL; + inputModifier = NULL; } -ConnectedInterface::~ConnectedInterface() { +ConnectedInterface::~ConnectedInterface() { if (outputPattern != NULL) delete outputPattern; } @@ -39,6 +41,7 @@ void ConnectedInterface::setOutputPattern(QList* pattern) { if (outputPattern != NULL) delete outputPattern; outputPattern = pattern; } + void ConnectedInterface::connectTo(ConnectedInterface *iface) { connectedTo.append(iface); @@ -97,3 +100,8 @@ ConnectedInterface *ConnectedInterface::getConnectionFromParentGroup() { } return NULL; } + +void ConnectedInterface::clearInputModifier() { + if (inputModifier != NULL) delete inputModifier; + inputModifier = NULL; +} diff --git a/ConnectedInterface.h b/ConnectedInterface.h index 64afb9e..f0a36a4 100644 --- a/ConnectedInterface.h +++ b/ConnectedInterface.h @@ -8,6 +8,8 @@ #include "AbstractInterface.h" class ReferenceInterface; +#include "AbstractInputModifier.h" + #include "Exception.h" @@ -28,14 +30,17 @@ public : // getters inline QList getConnectedTo() { return connectedTo;} - inline ConnectedInterface* getConnectedFrom() { return connectedFrom;} - inline QList* getOutputPattern() { return outputPattern; } + inline ConnectedInterface* getConnectedFrom() { return connectedFrom;} + inline QList* getOutputPattern() { return outputPattern; } + inline AbstractInputModifier* getInputModifier() { return inputModifier; } - // setters + // setters void setOutputPattern(QList* pattern); + inline void setInputModifier(AbstractInputModifier* mod) { inputModifier = mod; } // testers inline bool isConnectedTo(){return connectedTo.length() != 0;} + inline bool isConnectedToMany(){return connectedTo.length()>=2;} inline bool isConnectedFrom(){return connectedFrom != NULL;} virtual bool canConnectTo(AbstractInterface* iface) = 0; virtual bool canConnectFrom(AbstractInterface* iface) = 0; @@ -46,6 +51,7 @@ public : //bool connectFrom(ConnectedInterface* iface); ConnectedInterface* getConnectionToParentGroup(); ConnectedInterface* getConnectionFromParentGroup(); + void clearInputModifier(); virtual AbstractInterface *clone() = 0; //void removeConnectedTo(ConnectedInterface *inter); @@ -70,8 +76,9 @@ protected: * this interface. connecteFrom references such an interface if it exists. */ ConnectedInterface* connectedFrom; - - // patterns + AbstractInputModifier* inputModifier; // if needed, represent a block taht does not appear on screen but taht will modify the stream. + + // patterns QList* outputPattern; //! only usefull for output interfaces }; diff --git a/ConnectionItem.cpp b/ConnectionItem.cpp index 5dcd338..4de86cb 100644 --- a/ConnectionItem.cpp +++ b/ConnectionItem.cpp @@ -876,18 +876,22 @@ void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { /* have to check if the connection can be removed. If the from or to InterfaceItem is owned by a group item, and this item is both connected to and from, thus it is impossible to remove this connection + because there would be a group interface alone and not connected and this situation is not allowed. + + Nevertheless, there are 2 exceptions : + - a from group interface is connected to more than one input interface + - the connection is between a source block outside the top group and the top group */ bool canRemove = true; - InterfaceItem* groupIfaceItem = NULL; + if (fromInterfaceItem->getOwner()->isGroupItem()) { - groupIfaceItem = fromInterfaceItem; - } - else if (toInterfaceItem->getOwner()->isGroupItem()) { - groupIfaceItem = toInterfaceItem; + ConnectedInterface* ref = fromInterfaceItem->refInter; + if ((ref->isConnectedFrom()) && (ref->getConnectedTo().length() == 1)) { + canRemove = false; + } } - - if (groupIfaceItem != NULL) { - ConnectedInterface* ref = groupIfaceItem->refInter; + else if ((toInterfaceItem->getOwner()->isGroupItem()) && (! toInterfaceItem->getOwner()->getRefBlock()->isTopGroupBlock())) { + ConnectedInterface* ref = toInterfaceItem->refInter; if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) { canRemove = false; } diff --git a/DelayInputModifier.cpp b/DelayInputModifier.cpp new file mode 100644 index 0000000..a35aa21 --- /dev/null +++ b/DelayInputModifier.cpp @@ -0,0 +1,30 @@ +#include "DelayInputModifier.h" + +DelayInputModifier::DelayInputModifier(int _delayLength) : AbstractInputModifier() { + setDelayLength(_delayLength); +} + +void DelayInputModifier::setDelayLength(int _delayLength) { + if (_delayLength < 1) _delayLength = 1; + delayLength = _delayLength; +} + +QList* DelayInputModifier::getModifiedInput(QList* input) { + + pattern->clear(); + for(int i=0;iappend(0); + pattern->append(*input); + return pattern; +} + +QString DelayInputModifier::getTypeStr() { + return "delay"; +} + +QString DelayInputModifier::getParametersStr() { + return QString::number(delayLength); +} + +bool DelayInputModifier::isDelay() { + return true; +} diff --git a/DelayInputModifier.h b/DelayInputModifier.h new file mode 100644 index 0000000..1fda2ec --- /dev/null +++ b/DelayInputModifier.h @@ -0,0 +1,33 @@ +#ifndef __DELAYINPUTMODIFIER_H__ +#define __DELAYINPUTMODIFIER_H__ + +#include +#include + +#include "AbstractInputModifier.h" +using namespace std; +using namespace Qt; + +class DelayInputModifier : public AbstractInputModifier { + +public: + + DelayInputModifier(int _delayLength = 1); + // getters + inline int getDelayLength() { return delayLength; } + // setters + void setDelayLength(int _delayLength); + // testers + bool isDelay(); + + // others + QList* getModifiedInput(QList* input); + + QString getTypeStr(); + QString getParametersStr(); + +private: + int delayLength; +}; + +#endif // __DELAYINPUTMODIFIER_H__ diff --git a/Dispatcher.cpp b/Dispatcher.cpp index a416f95..a552f20 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -23,6 +23,10 @@ #include "BlockLibraryWidget.h" #include "BlockLibraryTree.h" +#include "AbstractInputModifier.h" +#include "DelayInputModifier.h" + + #include "InterfacePropertiesWindow.h" int Dispatcher::sceneCounter = 0; @@ -167,6 +171,25 @@ void Dispatcher::changeConnectionMode(int mode){ */ } +void Dispatcher::generateBlockVHDL(BoxItem *item){ + static QString fctName = "Dispatcher::generateBlockVHDL()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + if (item->getRefBlock()->isFunctionalBlock()) { + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + ReferenceBlock* ref = block->getReference(); + BlockImplementation* impl = ref->getImplementations().at(0); + try { + impl->generateVHDL(block,"/home/sdomas/"); + } + catch(Exception e) { + cout << qPrintable(e.getMessage()) << endl; + } + } +} + void Dispatcher::renameFunctionalBlock(BoxItem *item){ static QString fctName = "Dispatcher::renameFunctionalBlock()"; #ifdef DEBUG_FCTNAME @@ -341,13 +364,67 @@ void Dispatcher::showPatterns(InterfaceItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface()); - foreach(char c, *(iface->getOutputPattern())) { - cout << (int)c; + QString msg = ""; + if (item->refInter->getDirection() == AbstractInterface::Input) { + msg = "Input pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is:\n"; + ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface()); + ConnectedInterface* fromIface = iface->getConnectedFrom(); + if (fromIface->getOutputPattern() == NULL) return; + foreach(char c, *(fromIface->getOutputPattern())) { + msg += QString::number((int)c); + } + msg += "\n"; + } + else if (item->refInter->getDirection() == AbstractInterface::Output) { + msg = "Output pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is:\n"; + ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface()); + if (iface->getOutputPattern() == NULL) return; + foreach(char c, *(iface->getOutputPattern())) { + msg += QString::number((int)c); + } + msg += "\n"; + } + QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok); +} + +void Dispatcher::showModifier(InterfaceItem *item) { + static QString fctName = "Dispatcher::showModifier()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + QString msg = ""; + AbstractInputModifier* mod = item->refInter->getInputModifier(); + if (mod->isDelay()) { + DelayInputModifier* delay = (DelayInputModifier *)mod; + msg = "Pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is modified by a simple delay of "; + msg += QString::number(delay->getDelayLength()); + } - cout << endl; + QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok); } +void Dispatcher::removeModifier(InterfaceItem *item) { + static QString fctName = "Dispatcher::showModifier()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + item->refInter->clearInputModifier(); +} + + void Dispatcher::duplicateBoxItem(BoxItem *item){ static QString fctName = "Dispatcher::duplicateBoxItem()"; #ifdef DEBUG_FCTNAME @@ -430,12 +507,13 @@ void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) { } -void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { +BoxItem* Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { static QString fctName = "Dispatcher::addBlock()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif bool newSource = false; + BoxItem* item = NULL; GroupScene *scene = getSceneById(idScene); ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock); // if block has no inputs, propose to add it as a source to top scene @@ -452,9 +530,11 @@ void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { else { GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref); - scene->createBoxItem(newOne); + item = scene->createBoxItem(newOne); + params->blockToItem.insert(newOne,item); } params->unsaveModif = true; + return item; } @@ -482,6 +562,7 @@ GroupWidget *Dispatcher::createTopScene(){ // creating the view part of the group GroupItem *group = new GroupItem(NULL,refBlock,this,params); + // adding the fake interface to the top group item //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params); //group->addInterface(item,true); @@ -531,6 +612,7 @@ GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *up GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock()); // creating the view part of the group GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params); + // creating the group widget group = new GroupWidget(parentWidget, this, params); // getting the newly created scene @@ -834,6 +916,8 @@ void Dispatcher::removeBoxItem(BoxItem *item) { FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); item->getScene()->removeBoxItem(item); params->getGraph()->removeFunctionalBlock(block); + params->blockToItem.remove(block); + } else if (item->getRefBlock()->isGroupBlock()) { @@ -1114,3 +1198,31 @@ InterfaceItem* Dispatcher::getInterfaceItemById(int id) { return NULL; } +void Dispatcher::findGraphModifications(FunctionalBlock *block) { + static QString fctName = "Dispatcher::findGraphModifications()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + block->computeAdmittanceDelays(); + // get the block item that is associated to block + BoxItem* toBlockItem = params->blockToItem.value(block); + + /* VERSION 1: just add delays if needed */ + QMap* > delays = block->getAdmittanceDelays(); + QMapIterator* > iterD(delays); + while (iterD.hasNext()) { + iterD.next(); + QList* delay = iterD.value(); + if (delay->at(0) > 0) { + // create delay and associate it to the connected input + AbstractInputModifier* mod = new DelayInputModifier(delay->at(0)); + ConnectedInterface* toIface = AI_TO_CON(iterD.key()->getAssociatedIface()); + cout << "modify input of " << qPrintable(toIface->getName()) << endl; + toIface->setInputModifier(mod); + // repaint + toBlockItem->update(); + } + } +} + diff --git a/Dispatcher.h b/Dispatcher.h index 75583d4..ae4cc64 100644 --- a/Dispatcher.h +++ b/Dispatcher.h @@ -68,18 +68,20 @@ public slots: BoxItem* getBoxItemById(int id); GroupItem* getGroupItemById(int id); InterfaceItem* getInterfaceItemById(int id); - + // block ops - void addBlock(int idCategory, int idBlock, int idScene); + BoxItem* addBlock(int idCategory, int idBlock, int idScene); void removeBoxItem(BoxItem* item); void duplicateBoxItem(BoxItem* item); void renameFunctionalBlock(BoxItem* item); + void generateBlockVHDL(BoxItem* item); void renameGroupBlock(GroupItem* item); void renameSourceBlock(SourceItem* item); void removeSourceItem(SourceItem* item); void duplicateSourceItem(SourceItem* item); + // interface ops /*! * \brief connectInterToGroup @@ -113,6 +115,8 @@ public slots: void showProperties(InterfaceItem *inter); void renameInterface(InterfaceItem* item); void showPatterns(InterfaceItem* item); + void showModifier(InterfaceItem* item); + void removeModifier(InterfaceItem* item); // connection ops bool createConnection(InterfaceItem *iface1, InterfaceItem *iface2); @@ -120,6 +124,9 @@ public slots: void removeConnection(ConnectionItem *conn); + // analysis ops + void findGraphModifications(FunctionalBlock* block); // find modif so that block has compatible inputs + // others void showBlocksLibrary(); diff --git a/Exception.cpp b/Exception.cpp index 4036dac..9592e4d 100644 --- a/Exception.cpp +++ b/Exception.cpp @@ -1,14 +1,16 @@ #include "Exception.h" -Exception::Exception(int _id) { +Exception::Exception(int _id, void *_source) { id = _id; message = getDefaultMessage(); + source = _source; } Exception::Exception(const Exception& other) { id = other.id; message = other.message; + source = other.source; } QString Exception::getDefaultMessage() { @@ -51,6 +53,7 @@ QString Exception::getDefaultMessage() { case IP_AP_NOTCOMPAT : ret = tr("IP and AP not compatible"); break; case IP_END_NULLCOL : ret = tr("IP ends with anull column (normally not possible during compat. check)"); break; case AP_TOO_SHORT : ret = tr("AP has been badly computed, leading to a AP shorter than needed (NB: it is an abnormal case)"); break; + case IFACE_NOT_CONNECTED : ret = tr("an interface with control is not coonected, leading to an impossible graph analysis"); break; } return ret; diff --git a/Exception.h b/Exception.h index ce2ea72..e45e7bb 100644 --- a/Exception.h +++ b/Exception.h @@ -61,7 +61,8 @@ supp. infos : saved in UTF-8 [éè] // exception for patterns #define INVALID_REFBLOCK_USE 10001 -#define INVALID_DELTA_CP 10002 // delta and CP are not consistent (NB: used during admittance computation) +#define INVALID_GROUPBLOCK_USE 10002 +#define INVALID_DELTA_CP 10003 // delta and CP are not consistent (NB: used during admittance computation) #define EVAL_PARAM_UNKNOWN 10101 // a variable used in an expression is not defined as a block parameter #define EVAL_PARAM_NOVALUE 10102 // can't get the double value of a block parameter @@ -81,6 +82,7 @@ supp. infos : saved in UTF-8 [éè] #define IP_END_NULLCOL 10503 // IP ends with anull column (normally not possible during compat. check) #define AP_TOO_SHORT 10504 // AP has been badly computed, leading to a AP shorter than needed (NB: it is an abnormal case) +#define IFACE_NOT_CONNECTED 10601 // an interface with control is not connected => impossible to analyz the graph using namespace std; using namespace Qt; @@ -89,17 +91,19 @@ class Exception : public QObject { public: - Exception(int _id); + Exception(int _id, void* _source = NULL); Exception(const Exception& other); inline int getType() { return id; } inline void setMessage(QString _message) { message = _message; } inline QString getMessage() { return message; } QString getDefaultMessage(); + inline void* getSource() { return source; } private: int id; QString message; + void* source; }; diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 7be000a..91f4e03 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -184,6 +184,9 @@ void FunctionalBlock::createConsumptionPattern() throw(Exception) { cout << "call to " << qPrintable(fctName) << endl; #endif + // first clear if already exists + clearConsumptionPattern(); + lengthCP = -1; QHash consPattern = implementation->getConsumptionPattern(); @@ -191,7 +194,7 @@ void FunctionalBlock::createConsumptionPattern() throw(Exception) { FunctionalInterface* connIface = AI_TO_FUN(iface); QString refName = connIface->getReference()->getName(); if (! consPattern.contains(refName)) { - throw(Exception(NO_IFACE_CP)); + throw(Exception(NO_IFACE_CP,this)); cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl; } QList* pattern = NULL; @@ -207,7 +210,7 @@ void FunctionalBlock::createConsumptionPattern() throw(Exception) { } else { if (pattern->size() != lengthCP) { - throw(Exception(INVALID_IFACE_CP_LENGTH)); + throw(Exception(INVALID_IFACE_CP_LENGTH,this)); } } } @@ -218,6 +221,9 @@ void FunctionalBlock::createProductionPattern() throw(Exception){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + + // first clear if already exists + clearProductionPattern(); lengthPP = -1; QHash prodPattern = implementation->getProductionPattern(); @@ -226,7 +232,7 @@ void FunctionalBlock::createProductionPattern() throw(Exception){ FunctionalInterface* connIface = AI_TO_FUN(iface); QString refName = connIface->getReference()->getName(); if (! prodPattern.contains(refName)) { - throw(Exception(NO_IFACE_PP)); + throw(Exception(NO_IFACE_PP,this)); } QList* pattern = NULL; try { @@ -241,7 +247,7 @@ void FunctionalBlock::createProductionPattern() throw(Exception){ } else { if (pattern->size() != lengthPP) { - throw(Exception(INVALID_IFACE_PP_LENGTH)); + throw(Exception(INVALID_IFACE_PP_LENGTH,this)); } } } @@ -252,6 +258,10 @@ void FunctionalBlock::createProductionCounter() throw(Exception) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + + // first clear if already exists + productionCounter.clear(); + QStringList counterParts = implementation->getProductionCounter().split(","); foreach(QString s, counterParts) { @@ -266,7 +276,7 @@ void FunctionalBlock::createProductionCounter() throw(Exception) { s.chop(1); QStringList gen = s.split(":"); if (gen.size() != 3) { - throw(Exception(INVALID_IFACE_PC)); + throw(Exception(INVALID_IFACE_PC,this)); } int start = 0; int nb = 0; @@ -309,9 +319,21 @@ QList* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exce #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - - QList lst; - QString p = patternIn; + /* expanding a pattern is done in two steps : + - 1 : finding all variables that correspond to an expression + and copy them in the pattern + - 2 : parsing the result + + Note that the result MUST contain only variables that have a + integer/double value. Otherwise, expanding will fail. + + */ + + // first step. + + QString p = replaceExpressions(patternIn); + + QList lst; p.append(')'); int offset = 0; QList* patternOut = new QList(); @@ -325,6 +347,31 @@ QList* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exce return patternOut; } +QString FunctionalBlock::replaceExpressions(const QString& patternIn) throw(Exception) { + + QString res = patternIn; + bool stop = false; + QRegularExpression re("[$][a-zA-Z0-9_]+"); + + while (!stop) { + stop = true; + QRegularExpressionMatchIterator matcher = re.globalMatch(res); + while(matcher.hasNext()) { + QRegularExpressionMatch m = matcher.next(); + QString param = m.captured(0); + QString paramName = param; + paramName.remove(0,1); + BlockParameter* p = getParameterFromName(paramName); + if ((p != NULL) && (p->getType() == BlockParameter::Expression)) { + res.replace(param,p->getStringValue()); + stop = false; + cout << "found an expr: " << qPrintable(paramName) << ", patern => " << qPrintable(res) << endl; + } + } + } + return res; +} + QList FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset) throw(Exception) { QList patternOut; @@ -358,7 +405,7 @@ QList FunctionalBlock::expandPatternRecur(const QString& patternIn, int *o *offset += 1; } if (*offset == patternIn.size()) { - throw(Exception(INVALID_IFACE_PATTERN)); + throw(Exception(INVALID_IFACE_PATTERN,this)); } double repeat = 0; try { @@ -387,7 +434,7 @@ QList FunctionalBlock::expandPatternRecur(const QString& patternIn, int *o *offset += 1; } if (*offset == patternIn.size()) { - throw(Exception(INVALID_IFACE_PATTERN)); + throw(Exception(INVALID_IFACE_PATTERN,this)); } double repeat = 0; try { @@ -421,14 +468,14 @@ double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exce foreach (QString name, varNames) { QString paramName = name; paramName.remove(0,1); - BlockParameter* param = reference->getParameterFromName(paramName); + BlockParameter* param = getParameterFromName(paramName); if (param == NULL) { - throw(Exception(EVAL_PARAM_UNKNOWN)); + throw(Exception(EVAL_PARAM_UNKNOWN,this)); } bool okVal; - int val = param->getDoubleValue(&okVal); + int val = param->getDoubleValue(&okVal); if (!okVal) { - throw(Exception(EVAL_PARAM_NOVALUE)); + throw(Exception(EVAL_PARAM_NOVALUE,this)); } vars.insert(name,(double)val); } @@ -440,11 +487,152 @@ double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exce } catch(int index) { cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl; - throw(Exception(EVAL_INVALID_EXPR)); + throw(Exception(EVAL_INVALID_EXPR,this)); } return result; } +void FunctionalBlock::computeAdmittanceDelays() throw(Exception) { + static QString fctName = "FunctionalBlock::computeAdmittanceDelays()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + QList inClock; + QList delays; + + clearAdmittanceDelays(); + + // trying to synchronize the first one in AP + QMapIterator* > iterAP(admittance); + QMapIterator* > iterIP(inputPattern); + + while (iterAP.hasNext()) { + iterAP.next(); + iterIP.next(); + QList* ap = iterAP.value(); + QList* ip = iterIP.value(); + int first = 0; + while ((first < lengthIP) && (ip->at(first) == 0)) first++; + while ((first < lengthAP) && (ap->at(first) == 0)) first--; + delays.append(first); + inClock.append(0); + QList* delays = new QList(); + admittanceDelays.insert(iterAP.key(), delays); + } + + QMapIterator* > iterDelays(admittanceDelays); + + // get the delay to apply + int maxDelay = 0; + for(int i=0;i maxDelay) maxDelay = delays[i]; + } + // adding the delays to IP + iterIP.toFront(); + int i = 0; + while (iterIP.hasNext()) { + iterIP.next(); + iterDelays.next(); + QList* ip = iterIP.value(); + QList* d = iterDelays.value(); + d->append(maxDelay-delays[i]); + cout << "prependind " << qPrintable(iterIP.key()->getName()) << " with " << (maxDelay-delays[i]) << " 0" << endl; + for(int j=0;jprepend(0); + } + for(int j=0;jappend(0); + } + i++; + } + lengthIP += maxDelay; + + cout << "IP length = " << lengthIP << ", AP length = " << lengthAP << endl; + bool stop = false; + int apIndex = 0; + int ipIndex = 0; + while (!stop) { + + // if AP is a valid group, search for the next valid group in IP + if (isValidDataGroup(admittance,apIndex)) { + + while ((ipIndex < lengthIP) && (! isValidDataGroup(inputPattern,ipIndex))) ipIndex++; + if (ipIndex == lengthIP) { + stop = true; + continue; + } + } + + iterAP.toFront(); + iterIP.toFront(); + iterDelays.toFront(); + + if (samePatterns(inputPattern,ipIndex,admittance,apIndex)) { + while (iterAP.hasNext()) { + iterAP.next(); + iterDelays.next(); + QList* ap = iterAP.value(); + if (ap->at(apIndex) == 1) { + QList* d = iterDelays.value(); + d->append(0); // the 1 is at its good place, so no delay + } + } + } + else { + cout << "diff between IP and AP at " << apIndex << endl; + // search for the next 1 in IP for every input that has a 1 in AP + + while (iterAP.hasNext()) { + iterAP.next(); + iterIP.next(); + iterDelays.next(); + QList* ap = iterAP.value(); + QList* ip = iterIP.value(); + QList* d = iterDelays.value(); + // case 1: 1 in IP is too late + if ((ap->at(apIndex) == 1) && (ip->at(ipIndex) == 0)) { + int delay = 1; + while ( ((ipIndex+delay) < lengthIP) && (ip->at(ipIndex+delay) == 0) ) delay++; + cout << "found a delay of " << (-delay) << " for iface " << qPrintable(iterAP.key()->getName()) << endl; + // moving the 1 to its normal pos. + ip->replace(ipIndex,1); + ip->replace(ipIndex+delay,0); + d->append(-delay); + } + // case 2: 1 in IP is too soon + else if ((ap->at(apIndex) == 0) && (ip->at(ipIndex) == 1)) { + int delay = 1; + while ( ((apIndex+delay) < lengthAP) && (ap->at(apIndex+delay) == 0) ) delay++; + cout << "found a delay of " << delay << " for iface " << qPrintable(iterAP.key()->getName()) << endl; + // search for next 0 in IP to put the 1 + int k = ipIndex+delay; + while ((k < lengthIP) && (ip->at(k) == 1)) k++; + ip->replace(ipIndex,0); + ip->replace(k,1); + d->append(delay); + } + } + if (! samePatterns(inputPattern,inClock,admittance,apIndex)) { + cout << "Abnormal case while searching for delays" << endl; + } + } + + apIndex++; + ipIndex++; + if ((apIndex >= lengthAP) || (ipIndex >= lengthIP)) stop = true; + } + iterDelays.toFront(); + while (iterDelays.hasNext()) { + iterDelays.next(); + QList* d = iterDelays.value(); + foreach(int v, *d) { + cout << v << " "; + } + cout << endl; + } + +} + void FunctionalBlock::createInputPattern() throw(Exception) { static QString fctName = "FunctionalBlock::createInputPattern())"; #ifdef DEBUG_FCTNAME @@ -452,12 +640,27 @@ void FunctionalBlock::createInputPattern() throw(Exception) { #endif lengthIP = -1; - foreach(AbstractInterface* iface, getControlInputs()) { + foreach(AbstractInterface* iface, getControlInputs()) { + ConnectedInterface* connIface = AI_TO_CON(iface); + // check if it is connected + if (connIface->getConnectedFrom() == NULL) { + throw(Exception(IFACE_NOT_CONNECTED,this)); + } + // get the precursor output pattern QList* out = connIface->getConnectedFrom()->getOutputPattern(); + + ConnectedInterface* assoIface = AI_TO_CON(connIface->getAssociatedIface()); + AbstractInputModifier* modifier = assoIface->getInputModifier(); + // check if the input is modified + if (modifier != NULL) { + + out = modifier->getModifiedInput(out); + } + if (out->size() == 0) { clearInputPattern(); - throw(Exception(NO_IFACE_IP)); + throw(Exception(NO_IFACE_IP,this)); } if (lengthIP == -1) { lengthIP = out->size(); @@ -588,7 +791,7 @@ void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) { while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++; if (clock == lengthIP) { cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl; - throw(Exception(IP_END_NULLCOL)); + throw(Exception(IP_END_NULLCOL,this)); } } /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or @@ -596,13 +799,13 @@ void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) { */ if (! samePatterns(inputPattern,clock,admittance,i)) { cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl; - throw(Exception(IP_AP_NOTCOMPAT)); // IP and AP not compatible + throw(Exception(IP_AP_NOTCOMPAT,this)); // IP and AP not compatible } clock++; i++; } if (clock < lengthIP) { - throw(Exception(AP_TOO_SHORT)); + throw(Exception(AP_TOO_SHORT,this)); cerr << "Abnormal case: AP is to short" << endl; } } @@ -637,6 +840,8 @@ void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) { // in case of inputPattern not created, do it if (lengthIP <= 0) { + + cout << "Strange case: input pattern is not created while it is time to compute output pattern !" << endl; // collect the input patterns for each input try { createInputPattern(); @@ -876,6 +1081,26 @@ bool FunctionalBlock::samePatterns(const QMap* > return true; } +bool FunctionalBlock::samePatterns(const QMap* >& patternSrc, const QList &srcCols, const QMap* >& patternDest, int destCol) { + if (patternSrc.size() != srcCols.size()) return false; + if (patternSrc.size() != patternDest.size()) return false; + + QMapIterator* > iterSrc(patternSrc); + QListIterator iterSrcCol(srcCols); + QMapIterator* > iterDest(patternDest); + while (iterSrc.hasNext()) { + iterSrc.next(); + int srcCol = iterSrcCol.next(); + iterDest.next(); + QList* srcPat = iterSrc.value(); + QList* destPat = iterDest.value(); + if (srcCol >= srcPat->size()) return false; + if (destCol >= destPat->size()) return false; + if (srcPat->at(srcCol) != destPat->at(destCol)) return false; + } + return true; +} + bool FunctionalBlock::canCombinePatterns(const QMap* >& patternSrc, int srcCol, QMap* > patternDest, int destCol) { if (patternSrc.size() != patternDest.size()) return false; QMapIterator* > iterSrc(patternSrc); @@ -960,6 +1185,19 @@ bool FunctionalBlock::isValidDataGroup(const QMap* >& pattern, const QList offsets) { + QMapIterator* > iterSrc(pattern); + QListIterator iterOffsets(offsets); + while (iterSrc.hasNext()) { + iterSrc.next(); + int offset = iterOffsets.next(); + QList* srcPat = iterSrc.value(); + if (offset >= srcPat->size()) return false; + if (srcPat->at(offset) == 1) return true; + } + return false; +} + bool FunctionalBlock::isOnlyXDataGroup(const QMap *> &pattern, int offset) { QMapIterator* > iterSrc(pattern); while (iterSrc.hasNext()) { @@ -1005,6 +1243,16 @@ void FunctionalBlock::clearInputPattern() { lengthIP = -1; } +void FunctionalBlock::clearAdmittanceDelays() { + QMapIterator* > iterA(admittanceDelays); + while (iterA.hasNext()) { + iterA.next(); + QList* d = iterA.value(); + if (d != NULL) delete d; + } + admittanceDelays.clear(); +} + int FunctionalBlock::createTriggers() { triggers.clear(); /* NB: this method returns the number of executions that have been started diff --git a/FunctionalBlock.h b/FunctionalBlock.h index b3cfbc4..404ce17 100644 --- a/FunctionalBlock.h +++ b/FunctionalBlock.h @@ -33,6 +33,7 @@ public: inline QList getProductionCounter() { return productionCounter; } inline QMap* > getConsumptionPattern() { return consumptionPattern; } inline QMap* > getProductionPattern() { return productionPattern; } + inline QMap* > getAdmittanceDelays() { return admittanceDelays; } inline int getConsumptionPatternLength() { return lengthCP; } inline int getProductionPatternLength() { return lengthPP; } inline int getDelta() { return delta; } @@ -59,7 +60,8 @@ public: void createPatterns() throw(Exception); // called in Graph, before checking compatibility and computing output pattern void checkInputPatternCompatibility() throw(Exception); void computeOutputPattern(int nbExec = -1) throw(Exception); - + void computeAdmittanceDelays() throw(Exception); // compute differences between IP and admittance + private: // patterns void createDelta() throw(Exception); @@ -67,15 +69,18 @@ private: void createProductionPattern() throw(Exception); // initialize a QList for each interface from patterns defined in implementation void createProductionCounter() throw(Exception); // initialize a QList from counter defined in implementation void createAdmittance(int nbExec) throw(Exception); // initialize a QList from consumption pattern and delta + void clearConsumptionPattern(); void clearProductionPattern(); void createInputPattern() throw(Exception); void clearInputPattern(); + void clearAdmittanceDelays(); int createTriggers(); // compute the clock cycle at which the block is triggered double evaluateExpression(const QString& expression) throw(Exception); QList* expandPattern(const QString& patternIn) throw(Exception); QList expandPatternRecur(const QString& patternIn, int* offset) throw(Exception); + QString replaceExpressions(const QString& patternIn) throw(Exception); /*! * \brief samePatterns * \param patternSrc the pattern that must be tested with patternDest (is patternDest == patternDest) @@ -86,6 +91,7 @@ private: leaving the dest pattern in an inconsistent state. Thus, it is a good idea to call canCombine before. */ bool samePatterns(const QMap* >& patternSrc, int srcCol, const QMap* >& patternDest, int destCol); + bool samePatterns(const QMap* >& patternSrc, const QList& srcCols, const QMap* >& patternDest, int destCol); /*! * \brief canCombinePatterns * \param patternSrc the pattern that must be combined with patternDest (patternDest = patternDest OR patternSrc) @@ -129,6 +135,7 @@ private: * isValidGroup checks if there is at least one 1 in the column offset of pattern. */ bool isValidDataGroup(const QMap* >& pattern, int offset); + bool isValidDataGroup(const QMap* >& pattern, const QList offsets); /*! * \brief isOnlyXGroup * \param pattern the pattern to test @@ -146,8 +153,9 @@ private: void shiftRightPattern(const QMap* >& pattern, int offset); QMap* > consumptionPattern; - QMap admittanceCyclic; // the admittance expressed as prologue-cyclic part-eppilogue, deduced from admittance + QMap admittanceCyclic; // the admittance expressed as prologue-cyclic part-epilogue, deduced from admittance QMap* > admittance; // the admittance taking into account nb exec. + QMap* > admittanceDelays; // the delay between what should be consumed and IP QMap* > productionPattern; QMap* > inputPattern; QMap* > outputPattern; // CAUTION: the QList* must also be stored in the outputPattern attributes of AbstractInterface diff --git a/FunctionalInterface.cpp b/FunctionalInterface.cpp index 2fc093e..23fd482 100644 --- a/FunctionalInterface.cpp +++ b/FunctionalInterface.cpp @@ -17,6 +17,7 @@ FunctionalInterface::FunctionalInterface(AbstractBlock* _owner, ReferenceInterfa reference = _reference; name = reference->getName(); + type = reference->getType(); endianess = reference->getEndianess(); width = reference->getWidth(); direction = reference->getDirection(); diff --git a/Graph.cpp b/Graph.cpp index 4b24181..bd1eb70 100644 --- a/Graph.cpp +++ b/Graph.cpp @@ -138,12 +138,15 @@ void Graph::createPatterns() throw(Exception) { void Graph::resetPatternComputed() { foreach(AbstractBlock* block, sources) { block->setPatternComputed(false); + block->resetTraversalLevel(); } foreach(AbstractBlock* block, groups) { GroupBlock* group = AB_TO_GRP(block); group->setPatternComputed(false); + block->resetTraversalLevel(); foreach(AbstractBlock* inBlock, group->getBlocks()) { inBlock->setPatternComputed(false); + block->resetTraversalLevel(); } } } @@ -157,7 +160,7 @@ void Graph::computeOutputPatterns(int nbExec) throw(Exception) { throw(e); } - resetPatternComputed(); + resetPatternComputed(); // search for all block that are generators. QList generators; generators.append(sources); diff --git a/GroupBlock.cpp b/GroupBlock.cpp index 62fd6ec..b515b54 100644 --- a/GroupBlock.cpp +++ b/GroupBlock.cpp @@ -10,7 +10,7 @@ int GroupBlock::counter = 1; GroupBlock::GroupBlock(GroupBlock *_parent) throw(Exception) : AbstractBlock() { // force topGroup to false if this group has a parent - if (_parent != NULL) { + if (_parent != NULL) { topGroup = false; name = QString("sub_group")+"_"+QString::number(counter++); } @@ -108,14 +108,20 @@ void GroupBlock::removeGenericParameter(QString name) { void GroupBlock::createInputPattern() { foreach(AbstractInterface* iface, getControlInputs()) { ConnectedInterface* connIface = AI_TO_CON(iface); - QList* pattern = new QList(*(connIface->getConnectedFrom()->getOutputPattern())); - connIface->setOutputPattern(pattern); - } + QList* pattern = new QList(*(connIface->getConnectedFrom()->getOutputPattern())); + connIface->setOutputPattern(pattern); + } +} + +void GroupBlock::computeAdmittanceDelays() throw(Exception) { + throw(Exception(INVALID_GROUPBLOCK_USE)); } -void GroupBlock::checkInputPatternCompatibility() throw(Exception){ +void GroupBlock::checkInputPatternCompatibility() throw(Exception){ + throw(Exception(INVALID_GROUPBLOCK_USE)); } + void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) { static QString fctName = "GroupBlock::computeOutputPattern()"; @@ -125,7 +131,7 @@ void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) { cout << "computing output pattern of group " << qPrintable(name) << endl; - bool canCompute = false; + bool canCompute = false; // get the input pattern on each inputs createInputPattern(); @@ -133,28 +139,34 @@ void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) { // find blocks that are connected to that inputs and generators QList fifo; foreach(AbstractBlock* block, blocks) { - + bool addIt = false; // if a block is a generator and has control outputs, add it if (block->isGeneratorBlock()) { if (block->getControlOutputs().size() > 0) addIt = true; } else { - // if the block has a control input connected from an intput of the group, add it too + // if the block has all its connected inputs that are connected to an intput of the group, add it too + addIt = true; foreach(AbstractInterface* iface, block->getControlInputs()) { - //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl; + //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl; ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom(); //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl; - if (connFrom->getOwner() == this) { - addIt = true; + if (connFrom == NULL) { + addIt = false; + break; + } + else if (connFrom->getOwner() != this) { + addIt = false; break; } } } if (addIt) { cout << "adding " << qPrintable(block->getName()) << " to initialize the FIFO" << endl; - fifo.append(block); + block->setTraversalLevel(0); // level 0 = first blocks to be evaluated + fifo.append(block); } } @@ -162,47 +174,70 @@ void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) { AbstractBlock* block = fifo.takeFirst(); if (block->getPatternComputed()) continue; // block has already been processed + + cout << "computing compat and output for " << qPrintable(block->getName()) << endl; + try { block->checkInputPatternCompatibility(); } - catch(Exception e) { - cout << qPrintable(block->getName()) << " is not compatible with his input pattern" << endl; + catch(Exception e) { + cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl; throw(e); - } + } try { block->computeOutputPattern(); } - catch(Exception e) { + catch(Exception e) { cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl; - throw(e); + throw(e); } canCompute = true; block->setPatternComputed(true); - // add other blocks connected from block to the fifo + /* add other blocks connected from block to the fifo but only if + all their connected inputs are connected to blocks that have + a traversalLevel >=0 + */ foreach(AbstractInterface* iface, block->getControlOutputs()) { ConnectedInterface* conn = (ConnectedInterface*)iface; foreach(ConnectedInterface* connTo, conn->getConnectedTo()) { - /* if connTo is owned by a functional block - or by a group block that is within this, add the block to the fifo. - */ - if (connTo->getOwner()->isFunctionalBlock()) { - fifo.append(connTo->getOwner()); + + AbstractBlock* block1 = connTo->getOwner(); + cout << "testing if " << qPrintable(block1->getName()) << " has all connected inputs connected to already processed blocks" << endl; + bool addIt = true; + int maxLevel = 0; + + foreach(AbstractInterface* iface, block1->getControlInputs()) { + //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl; + ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom(); + //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl; + + if ((connFrom != NULL) && (connFrom->getOwner()->getPatternComputed() == false)) { + addIt = false; + break; + } + else { + if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel(); + } + } + + if (addIt) { + cout << "adding " << qPrintable(block1->getName()) << " to the FIFO" << endl; + block1->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated + fifo.append(block1); } - else if (connTo->getOwner() != this) { - fifo.append(connTo->getOwner()); - } } } } - + if (canCompute) { foreach(AbstractInterface* iface, getControlOutputs()) { ConnectedInterface* connIface = AI_TO_CON(iface); QList* pattern = new QList(*(connIface->getConnectedFrom()->getOutputPattern())); - connIface->setOutputPattern(pattern); + connIface->setOutputPattern(pattern); } setPatternComputed(true); - } + } + } diff --git a/GroupBlock.h b/GroupBlock.h index b3aaeaf..f7a9c2c 100644 --- a/GroupBlock.h +++ b/GroupBlock.h @@ -44,6 +44,7 @@ public: void checkInputPatternCompatibility() throw(Exception); void computeOutputPattern(int nbExec = -1) throw(Exception); + void computeAdmittanceDelays() throw(Exception); private: // patterns diff --git a/GroupWidget.cpp b/GroupWidget.cpp index 318e596..54cdfc1 100644 --- a/GroupWidget.cpp +++ b/GroupWidget.cpp @@ -154,13 +154,13 @@ void GroupWidget::createActions() { void GroupWidget::createToolbar() { toolbarEditMode = new QToolBar(tr("Mode")); toolbarAdd = new QToolBar(tr("Group")); - toolbarTools = new QToolBar(tr("Tools")); + //toolbarTools = new QToolBar(tr("Tools")); toolbarEditMode->addWidget(new QLabel("Mode")); - toolbarTools->addWidget(new QLabel("Tools")); + //toolbarTools->addWidget(new QLabel("Tools")); toolbarEditMode->addSeparator(); - toolbarTools->addSeparator(); + //toolbarTools->addSeparator(); toolbarEditMode->addWidget(butAddConnection); toolbarEditMode->addWidget(butEdit); @@ -169,13 +169,13 @@ void GroupWidget::createToolbar() { toolbarAdd->addAction(newEmptyGroupAct); toolbarAdd->addAction(newGroupAct); - toolbarTools->addAction(deleteAct); - toolbarTools->addAction(selectAllAct); - toolbarTools->addAction(unselectAllAct); + //toolbarTools->addAction(deleteAct); + //toolbarTools->addAction(selectAllAct); + //toolbarTools->addAction(unselectAllAct); layout->addWidget(toolbarEditMode,0,0); layout->addWidget(toolbarAdd,0,1); - layout->addWidget(toolbarTools,0,2); + //layout->addWidget(toolbarTools,0,2); } void GroupWidget::slotEdit() { diff --git a/InterfaceItem.cpp b/InterfaceItem.cpp index 10158d7..443cee0 100644 --- a/InterfaceItem.cpp +++ b/InterfaceItem.cpp @@ -128,6 +128,16 @@ void InterfaceItem::paint(QPainter *painter) { painter->drawPath(params->outArrow); } + // paint modifier box if needed + + if (refInter->getInputModifier() != NULL) { + painter->save(); + painter->translate(params->arrowWidth+params->arrowLineLength,0); + painter->drawRect(0,-5,10,10); + painter->restore(); + } + + // draw names if(selected) { painter->setPen(QPen(Qt::red,2)); @@ -164,7 +174,9 @@ void InterfaceItem::paint(QPainter *painter) { else if((owner->isBoxItem()) || (owner->isSourceItem())){ painter->drawText(-w,-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName()); } - } + } + + painter->restore(); } diff --git a/InterfacePropertiesWindow.cpp b/InterfacePropertiesWindow.cpp index 419b33e..6999a16 100644 --- a/InterfacePropertiesWindow.cpp +++ b/InterfacePropertiesWindow.cpp @@ -21,6 +21,9 @@ InterfacePropertiesWindow::InterfacePropertiesWindow(InterfaceItem *_inter, QWid layout->addWidget(new QLabel(inter->refInter->getDirectionString()), 4, 1); layout->addWidget(new QLabel("Purpose :"), 5, 0); layout->addWidget(new QLabel(inter->refInter->getPurposeString()), 5, 1); + layout->addWidget(new QLabel("Type :"), 6, 0); + layout->addWidget(new QLabel(inter->refInter->getTypeString()), 6, 1); + this->setLayout(layout); show(); diff --git a/MainWindow.cpp b/MainWindow.cpp index 38ec48a..79bc6f9 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -5,9 +5,8 @@ #include "GroupWidget.h" #include "GroupScene.h" #include "VHDLConverter.h" -#include "AbstractBoxItem.h" #include "Graph.h" -#include "GroupItem.h" +#include "FunctionalBlock.h" #include #include #include @@ -54,6 +53,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { cout << "all references and implementations are loaded" << endl; + params->createDelayBlock(); + // create the menu, action, ... dispatcher = new Dispatcher(params,this); params->setDispatcher(dispatcher); @@ -86,9 +87,11 @@ MainWindow::~MainWindow() {} void MainWindow::initialize() { projectMenuEnb = 0; + analysisMenuEnb = 0; stackedWidget->setCurrentIndex(0); enableProjectActions(true,PROJECT_NEW | PROJECT_OPEN, OP_RAZ); + enableAnalysisActions(false); stackedWidget->setCurrentIndex(0); @@ -195,11 +198,39 @@ void MainWindow::enableProjectActions(bool enbMenu, quint16 mask, quint8 op) { } } +void MainWindow::enableAnalysisActions(bool enbMenu, quint16 mask, quint8 op) { + if (enbMenu) { + analysisMenu->setEnabled(true); + } + else { + analysisMenu->setEnabled(false); + } + + if (op == OP_ADD) { + analysisMenuEnb = analysisMenuEnb | mask; + } + else if (op == OP_REM) { + analysisMenuEnb = (analysisMenuEnb | mask) ^ mask; + } + else if (op == OP_RAZ) { + analysisMenuEnb = mask; + } + + + if (analysisMenuEnb & ANALYSIS_ANALYZE) { + graphAnalysis->setEnabled(true); + } + else { + graphAnalysis->setEnabled(false); + } +} + void MainWindow::createMenus(){ allMenuBar = menuBar(); projectMenu = allMenuBar->addMenu(tr("&Project")); + analysisMenu = allMenuBar->addMenu(tr("&Analysis")); toolsMenu = allMenuBar->addMenu(tr("&Tools")); projectMenu->addAction(newProject); @@ -209,8 +240,10 @@ void MainWindow::createMenus(){ projectMenu->addAction(closeProject); projectMenu->addAction(openLibrary); - toolsMenu->addAction(newBlockWidgetAct); - toolsMenu->addAction(graphValidation); + analysisMenu->addAction(graphAnalysis); + + toolsMenu->addAction(vhdlToXmlAct); + } @@ -246,15 +279,15 @@ void MainWindow::createActions() { openLibrary->setStatusTip(tr("Open block library window")); connect(openLibrary, SIGNAL(triggered()), this, SLOT(slotOpenBlockLibrary())); - newBlockWidgetAct = new QAction(tr("&XML generator"), this); - newBlockWidgetAct->setIcon(QPixmap::fromImage(QImage("icons/new.ico"))); - newBlockWidgetAct->setStatusTip(tr("Create a new XML generator")); - connect(newBlockWidgetAct, SIGNAL(triggered()), this, SLOT(slotNewBlockWidget())); + vhdlToXmlAct = new QAction(tr("&XML generator"), this); + vhdlToXmlAct->setIcon(QPixmap::fromImage(QImage("icons/new.ico"))); + vhdlToXmlAct->setStatusTip(tr("Create a new XML generator")); + connect(vhdlToXmlAct, SIGNAL(triggered()), this, SLOT(slotVHDLToXml())); - graphValidation = new QAction(tr("&graph validation"), this); - graphValidation->setIcon(QPixmap::fromImage(QImage("icons/new.ico"))); - graphValidation->setStatusTip(tr("validate the graph")); - connect(graphValidation, SIGNAL(triggered()), this, SLOT(slotGraphValidation())); + graphAnalysis = new QAction(tr("&graph validation"), this); + graphAnalysis->setIcon(QPixmap::fromImage(QImage("icons/new.ico"))); + graphAnalysis->setStatusTip(tr("validate the graph")); + connect(graphAnalysis, SIGNAL(triggered()), this, SLOT(slotGraphAnalysis())); } @@ -273,6 +306,7 @@ void MainWindow::slotLoadProject(){ library->updateComboScene(); params->isCurrentProject = true; enableProjectActions(true, PROJECT_CLOSE | PROJECT_SAVE | PROJECT_SAVEAS | PROJECT_LIB, OP_RAZ); + enableAnalysisActions(true, ANALYSIS_ANALYZE, OP_RAZ); } else { QMessageBox msgBox; @@ -289,6 +323,7 @@ void MainWindow::slotLoadProject(){ void MainWindow::slotNewProject(){ enableProjectActions(true, PROJECT_CLOSE | PROJECT_SAVE | PROJECT_SAVEAS | PROJECT_LIB, OP_RAZ); + enableAnalysisActions(true, ANALYSIS_ANALYZE, OP_RAZ); GroupWidget* topGroup = dispatcher->createTopScene(); addTopGroup(topGroup); library->updateComboScene(); @@ -342,7 +377,7 @@ bool MainWindow::slotCloseProject(){ } -void MainWindow::slotNewBlockWidget() { +void MainWindow::slotVHDLToXml() { new VHDLConverter(); } @@ -372,12 +407,24 @@ void MainWindow::slotOpenBlockLibrary() { } -void MainWindow::slotGraphValidation() { - try { - params->getGraph()->computeOutputPatterns(5); +void MainWindow::slotGraphAnalysis() { + bool compat = true; + try { + params->getGraph()->computeOutputPatterns(1); } catch(Exception e) { - cerr << qPrintable(e.getMessage()) << endl; + cerr << qPrintable(e.getMessage()) << endl; + compat = false; + if (e.getType() == IP_AP_NOTCOMPAT) { + FunctionalBlock* toBlock = (FunctionalBlock*)(e.getSource()); + QString msg = tr(""); + msg.append(toBlock->getName()); + msg += " is not compatible with its input pattern.\nDo you want to launch automatic modification process to ensure the compatibility ?"; + int ret = QMessageBox::question(this,tr("Building references library"),msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + if (ret == QMessageBox::Ok) { + dispatcher->findGraphModifications(toBlock); + } + } } } diff --git a/MainWindow.h b/MainWindow.h index 99858c8..9664a96 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -23,7 +23,9 @@ class Graph; // defines for menus -#define TRACE_MENU (quint8)1 +#define PROJECT_MENU (quint8)1 +#define ANALYSIS_MENU (quint8)2 +#define TOOLS_MENU (quint8)3 // defines for actions #define NONE_ACT (quint16)0 @@ -35,6 +37,8 @@ class Graph; #define PROJECT_CLOSE (quint16)16 #define PROJECT_LIB (quint16)32 +#define ANALYSIS_ANALYZE (quint16)1 + #define OP_ADD (quint8)0 #define OP_REM (quint8)1 #define OP_RAZ (quint8)2 @@ -89,8 +93,11 @@ private: QMenu* projectMenu; quint16 projectMenuEnb; + QMenu* analysisMenu; + quint16 analysisMenuEnb; QMenu* toolsMenu; + // actions for project QAction* newProject; QAction* openProject; QAction* saveProject; @@ -98,9 +105,11 @@ private: QAction* closeProject; QAction* openLibrary; - QAction *newBlockWidgetAct; - QAction *graphValidation; + // actions for graph analysis + QAction *graphAnalysis; + // actions for tools + QAction *vhdlToXmlAct; // versioning related quint8 versionMaj; @@ -109,6 +118,7 @@ private: public slots: void enableProjectActions(bool enbMenu, quint16 mask = 0, quint8 op = 0); // default : add nothing + void enableAnalysisActions(bool enbMenu, quint16 mask = 0, quint8 op = 0); // default : add nothing private slots: void slotNewProject(); @@ -118,8 +128,9 @@ private slots: bool slotCloseProject(); void slotOpenBlockLibrary(); - void slotNewBlockWidget(); - void slotGraphValidation(); + void slotGraphAnalysis(); + + void slotVHDLToXml(); void slotCheckNewVersion(QNetworkReply *reply); }; diff --git a/Parameters.cpp b/Parameters.cpp index 322046d..d3a8dd4 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -24,6 +24,10 @@ #include "Exception.h" #include "BlocksToConfigureWidget.h" +#include "BlockParameterGeneric.h" + +#include "DelayInputModifier.h" + Parameters::Parameters() { categoryTree = NULL; arrowWidth = 5; @@ -81,6 +85,48 @@ ReferenceBlock* Parameters::getReferenceBlock(int idCategory, int idBlock) { return ref; } +void Parameters::createDelayBlock() { + delayRef = new ReferenceBlock("no.xml"); + delayRef->addCategory(100); + delayRef->setName("delay"); + + BlockCategory* cat = categoryTree->searchCategory(100); + cat->blocks.append(delayRef); + + AbstractInterface* interIn = new ReferenceInterface(delayRef,"data_in",AbstractInterface::Input, AbstractInterface::Data, "expression","$in_width"); + delayRef->addInterface(interIn); + AbstractInterface* interInCtl = new ReferenceInterface(delayRef,"data_in_enb",AbstractInterface::Input, AbstractInterface::Control, "boolean","1"); + delayRef->addInterface(interInCtl); + interInCtl->setAssociatedIface(interIn); + AbstractInterface* interOut = new ReferenceInterface(delayRef,"data_out",AbstractInterface::Output, AbstractInterface::Data, "expression","$in_width"); + delayRef->addInterface(interOut); + AbstractInterface* interOutCtl = new ReferenceInterface(delayRef,"data_out_enb",AbstractInterface::Output, AbstractInterface::Control, "boolean","1"); + delayRef->addInterface(interOutCtl); + interOutCtl->setAssociatedIface(interOut); + BlockParameter* param1 = new BlockParameterGeneric(delayRef,"in_width","natural","8"); + BlockParameter* param2 = new BlockParameterGeneric(delayRef,"dly_length","natural","1"); + delayRef->addParameter(param1); + delayRef->addParameter(param2); + delayImpl = new BlockImplementation("no.xml"); + delayImpl->setDelta("1"); + QHash consPattern; + consPattern.insert("data_in_enb","1"); + delayImpl->setConsumptionPattern(consPattern); + QHash prodPattern; + prodPattern.insert("data_out_enb","O{$dly_length}1"); + delayImpl->setProductionPattern(prodPattern); + delayImpl->setProductionCounter("1"); + delayRef->addImplementation(delayImpl); + delayImpl->setReference(delayRef); + if (! delayImpl->checkPatterns()) { + cout << "Delay block creation: failure" << endl; + } + else { + cout << "Delay block creation: success" << endl; + } + +} + void Parameters::validateXmlFile(const QString& xmlFileName, const QString& xsdFileName, XmlFileType fileType) throw(Exception) { @@ -398,6 +444,38 @@ GroupWidget *Parameters::loadProject(QDomElement root) throw(Exception) { } cout << "connections loaded and created succefully!" << endl; + QDomNodeList modifierNodes = root.elementsByTagName("modifier"); + + for(int i=0; irefInter->setInputModifier(mod); + + } else { + cout << "interfaces not found, modifiers setup canceled!" << endl; + } + } + cout << "modifiers loaded and created succefully!" << endl; + return topGroup; } @@ -539,7 +617,7 @@ void Parameters::loadReferencesFromXml() throw(Exception) { QString line = in.readLine(); line = in.readLine(); - if (!line.contains("")) { + if (!line.contains(" + + QList lstIfaceItem; + // search for modifiers + foreach(ConnectionItem* item, allConnections) { + InterfaceItem* fromIfaceItem = item->getFromInterfaceItem(); + AbstractInputModifier* mod = fromIfaceItem->refInter->getInputModifier(); + if (mod != NULL) { + if (!lstIfaceItem.contains(fromIfaceItem)) lstIfaceItem.append(fromIfaceItem); + } + InterfaceItem* toIfaceItem = item->getToInterfaceItem(); + mod = toIfaceItem->refInter->getInputModifier(); + if (mod != NULL) { + if (!lstIfaceItem.contains(toIfaceItem)) lstIfaceItem.append(toIfaceItem); + } + } + // write input modifiers + writer.writeStartElement("modifiers"); + foreach(InterfaceItem* item, lstIfaceItem) { + AbstractInputModifier* mod = item->refInter->getInputModifier(); + if (mod != NULL) { + writer.writeStartElement("modifier"); + writer.writeAttribute("id", QString::number(item->getId())); + writer.writeAttribute("type",mod->getTypeStr()); + writer.writeAttribute("params", mod->getParametersStr()); + writer.writeEndElement(); + } + } + + writer.writeEndElement(); // writer.writeEndElement(); //getBoxItems()){ + if(item->getRefBlock() == block) { + return item; + } + } + + BoxItem* item = NULL; + foreach(GroupScene *s, scene->getChildrenScene()) { + item = searchFunctionalBlockRecur(block,s); + if (item != NULL) return item; + } + return NULL; +} + InterfaceItem* Parameters::searchInterfaceItemById(int id, GroupScene* scene) { foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){ diff --git a/Parameters.h b/Parameters.h index 27dc08f..8a71cfb 100644 --- a/Parameters.h +++ b/Parameters.h @@ -16,6 +16,7 @@ class ReferenceBlock; class GroupBlock; class FunctionalBlock; class GroupScene; +class AbstractBoxItem; class GroupItem; class BoxItem; class InterfaceItem; @@ -85,7 +86,8 @@ public : QList implPathes; QList availableBlocks; QList availableImplementations; - + ReferenceBlock* delayRef; + BlockImplementation* delayImpl; QString refLib; QString implLib; @@ -120,6 +122,7 @@ public : EditState editState; // takes values from EDIT_STATE_XXX bool unsaveModif; bool isRstClkShown; + QMap blockToItem; // allow to retrieve a box item from a functionnal block Graph* createGraph(); void destroyGraph(); @@ -137,6 +140,7 @@ public : void loadReferencesFromXml() throw(Exception); void loadReferencesFromLib() throw(Exception); void saveReferencesToLib() throw(Exception); + void createDelayBlock(); void loadImplementationsFromXml() throw(Exception); void loadImplementationsFromLib() throw(Exception); @@ -153,6 +157,8 @@ public : ReferenceBlock* searchBlockByXml(QString xmlName); ReferenceBlock* searchBlockByMd5(QString sumMd5); + BoxItem* searchFunctionalBlock(AbstractBlock* block); + void save(QString confFile); @@ -169,6 +175,7 @@ private: GroupScene* searchSceneById(int id, GroupScene* scene); BoxItem* searchBlockItemById(int id, GroupScene* scene); + BoxItem* searchFunctionalBlockRecur(AbstractBlock* block, GroupScene* scene); GroupItem* searchGroupItemById(int id, GroupScene* scene); InterfaceItem* searchInterfaceItemById(int id, GroupScene *scene); diff --git a/ParametersWindow.cpp b/ParametersWindow.cpp index ee98880..3fe11ea 100644 --- a/ParametersWindow.cpp +++ b/ParametersWindow.cpp @@ -5,8 +5,7 @@ #include "AbstractBlock.h" ParametersWindow::ParametersWindow(AbstractBlock *_block, Parameters *_params, BlocksToConfigureWidget *btcw, QWidget *parent) : - QWidget(parent) -{ + QWidget(parent) { block = _block; confWidget = btcw; params = _params; @@ -51,8 +50,7 @@ ParametersWindow::ParametersWindow(AbstractBlock *_block, Parameters *_params, B show(); } -void ParametersWindow::updateData() -{ +void ParametersWindow::updateData() { BlockParameter *param = block->getParameters().at(comboBox->currentIndex()); name->setText(param->getName()); value->setText(param->getValue().toString()); diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp index 037c644..fbf7828 100644 --- a/ReferenceBlock.cpp +++ b/ReferenceBlock.cpp @@ -104,11 +104,16 @@ void ReferenceBlock::loadInformations(QDomElement &elt) throw(Exception) { QString idsStr = eltCat.attribute("ids","none"); if (idsStr == "none") throw (Exception(BLOCKFILE_CORRUPTED)); - QStringList listCat = idsStr.split(","); - foreach(QString str, listCat) - { - int idCat = str.toInt(&ok); - categories.append(idCat); + if (idsStr.isEmpty()) { + categories.append(99); + } + else { + QStringList listCat = idsStr.split(","); + foreach(QString str, listCat) + { + int idCat = str.toInt(&ok); + categories.append(idCat); + } } // getting description @@ -417,6 +422,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i)); if (iface->getPurpose() == AbstractInterface::Control) { toWrite << iface->getName(); + toWrite << iface->getType(); toWrite << iface->getWidth(); toWrite << iface->getPurpose(); toWrite << iface->getDirection(); @@ -428,6 +434,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i)); if (iface->getPurpose() != AbstractInterface::Control) { toWrite << iface->getName(); + toWrite << iface->getType(); toWrite << iface->getWidth(); toWrite << iface->getPurpose(); toWrite << iface->getDirection(); @@ -440,6 +447,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i)); if (iface->getPurpose() == AbstractInterface::Control) { toWrite << iface->getName(); + toWrite << iface->getType(); toWrite << iface->getWidth(); toWrite << iface->getPurpose(); toWrite << iface->getDirection(); @@ -451,6 +459,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { ReferenceInterface *iface = (ReferenceInterface *)(b.outputs.at(i)); if (iface->getPurpose() != AbstractInterface::Control) { toWrite << iface->getName(); + toWrite << iface->getType(); toWrite << iface->getWidth(); toWrite << iface->getPurpose(); toWrite << iface->getDirection(); @@ -461,6 +470,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { for(int i=0; igetName(); + toWrite << iface->getType(); toWrite << iface->getWidth(); toWrite << iface->getPurpose(); toWrite << iface->getDirection(); @@ -535,6 +545,9 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { iface = new ReferenceInterface(&b); in >> txt; iface->setName(txt); + int type; + in >> type; + iface->setType(type); in >> txt; iface->setWidth(txt); in >> val; @@ -561,6 +574,9 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { iface = new ReferenceInterface(&b); in >> txt; iface->setName(txt); + int type; + in >> type; + iface->setType(type); in >> txt; iface->setWidth(txt); in >> val; @@ -587,6 +603,9 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { iface = new ReferenceInterface(&b); in >> txt; iface->setName(txt); + int type; + in >> type; + iface->setType(type); in >> txt; iface->setWidth(txt); in >> val; @@ -609,3 +628,8 @@ void ReferenceBlock::computeOutputPattern(int nbExec) throw(Exception) { // does strictly nothing throw(Exception(INVALID_REFBLOCK_USE)); } + +void ReferenceBlock::computeAdmittanceDelays() throw(Exception) { + // does strictly nothing + throw(Exception(INVALID_REFBLOCK_USE)); +} diff --git a/ReferenceBlock.h b/ReferenceBlock.h index b1ebd84..baa8aaf 100644 --- a/ReferenceBlock.h +++ b/ReferenceBlock.h @@ -70,6 +70,7 @@ private: // patterns void checkInputPatternCompatibility() throw(Exception); void computeOutputPattern(int nbExec = -1) throw(Exception); + void computeAdmittanceDelays() throw(Exception); }; #endif // __REFERENCEBLOCK_H__ diff --git a/SourceItem.cpp b/SourceItem.cpp index ca252c1..6c2b30d 100644 --- a/SourceItem.cpp +++ b/SourceItem.cpp @@ -630,7 +630,7 @@ void SourceItem::load(QDomElement funcElement) throw(Exception) { BlockParameter *blockParam = NULL; blockParam = functionalBlock->getParameterFromName(name); if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED)); - blockParam->setValue(value); + blockParam->setValue(value); } // recreate all (non-control) interfaces because of some may have a multiplicity>1 with several examplars diff --git a/VHDLConverter.cpp b/VHDLConverter.cpp index 42fff3a..d3938b2 100644 --- a/VHDLConverter.cpp +++ b/VHDLConverter.cpp @@ -826,11 +826,12 @@ void VHDLConverter::replaceSignalNames(QString& line) { void VHDLConverter::updateArchitecture() { QRegularExpression rxLT("<=",QRegularExpression::CaseInsensitiveOption); QRegularExpression rxGT("=>",QRegularExpression::CaseInsensitiveOption); - foreach(QString line, archLines) { + for(int i=0;i - + EnvironmentId - {3701e197-5b6c-48ea-9e98-a6cf6de18672} + {c8006d66-d34f-42be-ad10-d0207752286d} ProjectExplorer.Project.ActiveTarget @@ -61,7 +61,7 @@ Desktop Desktop - {ed04208c-8774-456b-99b9-4a02094ca7a4} + {2c9bf876-3476-44eb-8065-1f0844704dda} 0 0 0 diff --git a/blast.creator.user.3701e19 b/blast.creator.user.3701e19 new file mode 100755 index 0000000..95274be --- /dev/null +++ b/blast.creator.user.3701e19 @@ -0,0 +1,199 @@ + + + + + + EnvironmentId + {3701e197-5b6c-48ea-9e98-a6cf6de18672} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + qt2 + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 2 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 4 + false + 1 + true + true + false + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {ed04208c-8774-456b-99b9-4a02094ca7a4} + 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 + 0 + + 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 + + + + false + %{buildDir} + Exécutable personnalisé + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/blast.files b/blast.files index 22c212e..3c08c87 100755 --- a/blast.files +++ b/blast.files @@ -1,5 +1,9 @@ Exception.h Exception.cpp +AbstractInputModifier.h +AbstractInputModifier.cpp +DelayInputModifier.h +DelayInputModifier.cpp AbstractBlock.h AbstractBlock.cpp AbstractBoxItem.h diff --git a/blastconfig.xml b/blastconfig.xml index bc2d2bc..0abb637 100644 --- a/blastconfig.xml +++ b/blastconfig.xml @@ -1,6 +1,6 @@ - + @@ -9,7 +9,8 @@ - + + diff --git a/blastconfig.xsd b/blastconfig.xsd index f254ff6..ef4a2fa 100644 --- a/blastconfig.xsd +++ b/blastconfig.xsd @@ -168,7 +168,6 @@ - diff --git a/boxfilter_3x3.vhd b/boxfilter_3x3.vhd new file mode 100644 index 0000000..2998a41 --- /dev/null +++ b/boxfilter_3x3.vhd @@ -0,0 +1,421 @@ +------------------------------------------------------------------------------- +-- +-- File : boxfilter_3x3.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a box (i.e. average) filter with a 3x3 mask +-- on a grayscale image. The width of the image must be <= 1024. +-- Image size must be provided via generics +-- +-- Note : +-- CP = 1{$img_width*$img_height} +-- PP = 0{$img_width+7}1{$img_width*$img_height} +-- PC = {$img_width+2:$img_width*$img_height-($img_width+2):1},{$img_width*$img_height:$img_width+2,0} +-- delta = $img_width*$img_height +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity boxfilter_3x3 is + generic( + img_width : natural := 128; + img_height : natural := 128; + dsp_in_width : natural := 18; + dsp_out_width : natural := 36 + ); + port( + clk : in std_logic; + reset : in std_logic; + pix_in : in std_logic_vector(7 downto 0); + pix_in_enb : in std_logic; + pix_out : out std_logic_vector(7 downto 0); + pix_out_enb : out std_logic + ); +end boxfilter_3x3; + + +architecture rtl of boxfilter_3x3 is + + component ram_dp_1024x8 + port ( + clka : in std_logic; + wea : in std_logic_vector(0 downto 0); + addra : in std_logic_vector(9 downto 0); + dina : in std_logic_vector(7 downto 0); + douta : out std_logic_vector(7 downto 0); + clkb : in std_logic; + web : in std_logic_vector(0 downto 0); + addrb : in std_logic_vector(9 downto 0); + dinb : in std_logic_vector(7 downto 0); + doutb : out std_logic_vector(7 downto 0) + ); + end component; + + -- Signals + + -- constant signal set tup to img limits + signal count_col_end : unsigned (9 downto 0); + signal count_row_end : unsigned (9 downto 0); + + -- for storing image rows + signal sel_mem : unsigned (1 downto 0); -- the current memorize row + signal wea_0 : std_logic_vector(0 downto 0); -- we for memorized row 0 + signal wea_1 : std_logic_vector(0 downto 0); -- we for memorized row 1 + signal wea_2 : std_logic_vector(0 downto 0); -- we for memorized row 2 + + signal dina_0 : std_logic_vector(7 downto 0); + signal dina_1 : std_logic_vector(7 downto 0); + signal dina_2 : std_logic_vector(7 downto 0); + signal dina : std_logic_vector(7 downto 0); + + signal addra_w : std_logic_vector(9 downto 0); + signal addra_w_s : unsigned (9 downto 0); + signal wea : std_logic; + + + signal addrb_r : std_logic_vector(9 downto 0); -- addr where to store + signal addrb_r_s : unsigned (9 downto 0); -- addr where to store + + signal doutb_0 : std_logic_vector(7 downto 0); + signal doutb_1 : std_logic_vector(7 downto 0); + signal doutb_2 : std_logic_vector(7 downto 0); + + signal count_row_w : unsigned (10 downto 0); -- row counter while storing + signal store_last_pix : std_logic; -- to be sure that last pixel is stored + signal first_row_w : std_logic; -- '1' when the first row is read so that + -- mem_0 is filled with zeroes + signal all_pix_stored : std_logic; -- '1' when all pixels have been stored + + -- for reading image rows + signal start_read : std_logic; + signal do_read : std_logic; + signal count_row_r : unsigned (10 downto 0); + signal count_row_r_dly : unsigned (10 downto 0); + signal wea_dly : std_logic; + signal end_read : std_logic; + + -- for doing sums + signal do_sum : std_logic; + signal sum1 : unsigned (9 downto 0); + signal sum2 : unsigned (9 downto 0); + signal sum3 : unsigned (9 downto 0); + + -- for doing total + signal do_total : std_logic; + signal sum : unsigned (dsp_in_width-1 downto 0); + signal count_col_total : unsigned (10 downto 0); + signal count_row_total : unsigned (10 downto 0); + signal jump_first_sum : std_logic; + + -- for doing final division + signal do_div : std_logic; + signal do_out : std_logic; + signal end_filter : std_logic; + signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 14564 (=2^17/9) + signal mult_result : unsigned (dsp_out_width-1 downto 0); + + +begin + + img_row_0 : ram_dp_1024x8 + port map ( + clka => clk, + wea => wea_0, + addra => addra_w, + dina => dina_0, + clkb => clk, + web => (others => '0'), + addrb => addrb_r, + dinb => (others => '0'), + doutb => doutb_0 + ); + img_row_1 : ram_dp_1024x8 + port map ( + clka => clk, + wea => wea_1, + addra => addra_w, + dina => dina_1, + clkb => clk, + web => (others => '0'), + addrb => addrb_r, + dinb => (others => '0'), + doutb => doutb_1 + ); + img_row_2 : ram_dp_1024x8 + port map ( + clka => clk, + wea => wea_2, + addra => addra_w, + dina => dina_2, + clkb => clk, + web => (others => '0'), + addrb => addrb_r, + dinb => (others => '0'), + doutb => doutb_2 + ); + + + cst_mult <= to_unsigned(14564, dsp_in_width); + count_col_end <= to_unsigned(img_width-1, 10); + count_row_end <= to_unsigned(img_height-1, 10); + + addra_w <= std_logic_vector(addra_w_s); + addrb_r <= std_logic_vector(addrb_r_s); + + wea_0 <= "1" when ((sel_mem = 0 or first_row_w = '1') and wea = '1') else + "0"; + wea_1 <= "1" when (sel_mem = 1 and wea = '1') else + "0"; + wea_2 <= "1" when (sel_mem = 2 and wea = '1') else + "0"; + + dina_0 <= (others => '0') when (first_row_w = '1') else + dina; + + dina_1 <= dina; + dina_2 <= dina; + + store_row_process : process (clk, reset) + begin + if reset = '1' then + + sel_mem <= to_unsigned(0, 2); + addra_w_s <= to_unsigned(img_width-1, 10); + dina <= (others => '0'); + + wea <= '0'; + count_row_w <= to_unsigned(0, 11); + + start_read <= '0'; + first_row_w <= '1'; + store_last_pix <= '0'; + all_pix_stored <= '0'; + + elsif rising_edge(clk) then + + wea <= '0'; + start_read <= '0'; + dina <= (others => '0'); + store_last_pix <= '0'; + + -- reset all when filter has ended + if end_filter = '1' then + + count_row_w <= to_unsigned(0, 11); + sel_mem <= to_unsigned(0, 2); + addra_w_s <= to_unsigned(img_width-1, 10); + first_row_w <= '1'; + all_pix_stored <= '0'; + + elsif store_last_pix = '1' then + addra_w_s <= to_unsigned(0, 10); + -- select next ram + if sel_mem = 2 then + sel_mem <= to_unsigned(0, 2); + else + sel_mem <= sel_mem + 1; + end if; + all_pix_stored <= '1'; -- all pixels are stored + + elsif pix_in_enb = '1' then + + -- prepare to write + wea <= '1'; + -- take input + dina <= pix_in; + -- check if this is the last pixel + if addra_w_s = img_width-2 and count_row_w = img_height then + store_last_pix <= '1'; + end if; + -- if at line end + if addra_w_s = img_width-1 then + -- back to 0 + addra_w_s <= to_unsigned(0, 10); + -- select next ram + if sel_mem = 2 then + sel_mem <= to_unsigned(0, 2); + else + sel_mem <= sel_mem + 1; + end if; + -- end of first line to store + if count_row_w = 1 then + first_row_w <= '0'; + start_read <= '1'; + end if; + count_row_w <= count_row_w + 1; + else + addra_w_s <= addra_w_s + 1; + end if; + end if; + end if; + + end process store_row_process; + + read_rows_process : process (clk, reset) + begin + if reset = '1' then + + addrb_r_s <= to_unsigned(0, 10); + do_read <= '0'; + wea_dly <= '0'; + + count_row_r <= to_unsigned(0, 11); + end_read <= '0'; + + do_sum <= '0'; + + elsif rising_edge(clk) then + + wea_dly <= wea; + do_sum <= '0'; + end_read <= '0'; + + if end_read = '1' then + do_sum <= '1'; + end if; + + if start_read = '1' then + do_read <= '1'; + + elsif do_read = '1' and (all_pix_stored = '1' or wea_dly = '1') then + + do_sum <= '1'; + -- whatever the case inc addr if not at end + if addrb_r_s = img_width-1 then + addrb_r_s <= to_unsigned(0, 10); + if count_row_r = img_height-1 then + count_row_r <= to_unsigned(0, 11); + do_read <= '0'; + end_read <= '1'; + else + count_row_r <= count_row_r+1; + end if; + else + addrb_r_s <= addrb_r_s + 1; + end if; + end if; + end if; + + end process read_rows_process; + + sum_process : process (clk, reset) + begin + if reset = '1' then + + sum1 <= to_unsigned(0, 10); + sum2 <= to_unsigned(0, 10); + sum3 <= to_unsigned(0, 10); + count_row_r_dly <= to_unsigned(0, 11); + do_total <= '0'; + + elsif rising_edge(clk) then + + do_total <= '0'; + count_row_r_dly <= count_row_r; + + if end_filter = '1' then + sum1 <= to_unsigned(0, 10); + sum2 <= to_unsigned(0, 10); + sum3 <= to_unsigned(0, 10); + end if; + if do_sum = '1' then + + sum3 <= sum2; + sum2 <= sum1; + if count_row_r_dly = img_height-1 then + if sel_mem = 0 then + sum1 <= unsigned("00" & doutb_1) + unsigned("00" & doutb_2); + elsif sel_mem = 1 then + sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_2); + elsif sel_mem = 2 then + sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1); + end if; + else + sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1) + unsigned("00" & doutb_2); + end if; + do_total <= '1'; + end if; + end if; + + end process sum_process; + + total_process : process (clk, reset) + begin + if reset = '1' then + + sum <= to_unsigned(0, dsp_in_width); + + jump_first_sum <= '0'; + count_row_total <= to_unsigned(0, 11); + count_col_total <= to_unsigned(0, 11); + do_div <= '0'; + end_filter <= '0'; + + elsif rising_edge(clk) then + + do_div <= '0'; + end_filter <= '0'; + + if do_total = '1' then + + if jump_first_sum = '1' then + -- sum for the end of the line + if count_col_total = img_width-1 then + sum <= resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width); + count_col_total <= to_unsigned(0, 11); + if count_row_total = img_height-1 then + end_filter <= '1'; + count_row_total <= to_unsigned(0, 11); + jump_first_sum <= '0'; + else + count_row_total <= count_row_total + 1; + end if; + -- sum for the begining of the line + elsif count_col_total = 0 then + sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width); + count_col_total <= to_unsigned(1, 11); + else + sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width); + count_col_total <= count_col_total + 1; + end if; + do_div <= '1'; + else + jump_first_sum <= '1'; + end if; + end if; + + + end if; + + end process total_process; + + final_div_process : process (clk, reset) + begin + if reset = '1' then + + mult_result <= to_unsigned(0, dsp_out_width); + do_out <= '0'; + + elsif rising_edge(clk) then + + do_out <= '0'; + + if do_div = '1' then + mult_result <= sum * cst_mult; + do_out <= '1'; + end if; + end if; + end process final_div_process; + + pix_out <= std_logic_vector(mult_result(24 downto 17)); + pix_out_enb <= do_out; + +end rtl; + diff --git a/checker.vhd b/checker.vhd new file mode 100644 index 0000000..82ca1d3 --- /dev/null +++ b/checker.vhd @@ -0,0 +1,94 @@ +------------------------------------------------------------------------------- +-- +-- File : checker.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a threshold on an input +-- +-- +-- Note : The input is compared to one (or two) values and depending +-- on the result and the type of the comparison, the check output +-- is asserted to 1 or not. +-- The values are fixed by generic parameter. +-- The type of check is fixed by a generic paramter +-- type 1 : test if lesser or equal than X +-- type 2 : test if gretar or equal than X +-- type 3 : test if greater or equal than X and lesser or equal than Y +-- +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity checker is + generic( + in_width : natural := 8; + check_type : natural := 1; + inf_value : natural := 0; + sup_value : natural := 0 + ); + port( + clk : in std_logic; + reset : in std_logic; + data_in : in std_logic_vector(in_width-1 downto 0); + data_in_enb : in std_logic; + data_out : out std_logic_vector(in_width-1 downto 0); + data_out_enb : out std_logic; + check_out : out std_logic; + check_out_enb : out std_logic + ); +end checker; + + +architecture rtl of checker is + +begin + + check_process : process (clk, reset) + begin + if reset = '1' then + + check_out <= '0'; + data_out <= (others => '0'); + data_out_enb <= '0'; + check_out_enb <= '0'; + + elsif rising_edge(clk) then + + check_out <= '0'; + data_out <= (others => '0'); + data_out_enb <= '0'; + check_out_enb <= '0'; + + if data_in_enb = '1' then + + data_out <= data_in; + data_out_enb <= '1'; + check_out_enb <= '1'; + + if check_type = 1 then + if unsigned(data_in) <= inf_value then + check_out <= '1'; + end if; + elsif check_type = 2 then + if unsigned(data_in) >= inf_value then + check_out <= '1'; + end if; + elsif check_type = 3 then + if unsigned(data_in) >= inf_value and unsigned(data_in) <= sup_value then + check_out <= '1'; + end if; + end if; + end if; + end if; + + end process check_process; + +end rtl; + diff --git a/deserializer_3x1.vhd b/deserializer_3x1.vhd new file mode 100644 index 0000000..aaccecc --- /dev/null +++ b/deserializer_3x1.vhd @@ -0,0 +1,96 @@ +------------------------------------------------------------------------------- +-- +-- File : deserializer_3x1.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a deserialization of 3 element into +-- 3 parallel outputs +-- +-- +-- Note : +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity deserializer_3x1 is + generic( + in_width : natural := 8 + ); + port( + clk : in std_logic; + reset : in std_logic; + data_in : in std_logic_vector(in_width-1 downto 0); + data_in_enb : in std_logic; + data1_out : out std_logic_vector(in_width-1 downto 0); + data1_out_enb : out std_logic; + data2_out : out std_logic_vector(in_width-1 downto 0); + data2_out_enb : out std_logic; + data3_out : out std_logic_vector(in_width-1 downto 0); + data3_out_enb : out std_logic + + ); +end deserializer_3x1; + + +architecture rtl of deserializer_3x1 is + + -- Signals + signal do_out : std_logic; + signal data1_reg : std_logic_vector(in_width-1 downto 0); + signal data2_reg : std_logic_vector(in_width-1 downto 0); + + signal count : unsigned(1 downto 0); + +begin + + deser_process : process (clk, reset) + begin + if reset = '1' then + count <= to_unsigned(0, 2); + data1_reg <= (others => '0'); + data2_reg <= (others => '0'); + data1_out <= (others => '0'); + data2_out <= (others => '0'); + data3_out <= (others => '0'); + do_out <= '0'; + + elsif rising_edge(clk) then + + do_out <= '0'; + data1_out <= (others => '0'); + data2_out <= (others => '0'); + data3_out <= (others => '0'); + + if data_in_enb = '1' then + + if count = 0 then + data1_reg <= data_in; + count <= count + 1; + elsif count = 1 then + data2_reg <= data_in; + count <= count + 1; + elsif count = 2 then + data1_out <= data1_reg; + data2_out <= data2_reg; + data3_out <= data_in; + do_out <= '1'; + count <= to_unsigned(0, 2); + end if; + end if; + end if; + + end process deser_process; + + data1_out_enb <= do_out; + data2_out_enb <= do_out; + data3_out_enb <= do_out; + +end rtl; + diff --git a/lib/implementations/boxfilter_3x3_impl.xml b/lib/implementations/boxfilter_3x3_impl.xml new file mode 100644 index 0000000..6776fc1 --- /dev/null +++ b/lib/implementations/boxfilter_3x3_impl.xml @@ -0,0 +1,402 @@ + + + + + + + frdfgdr + gregre + + + + + + + + +component ram_dp_1024x8 +port ( +clka : in std_logic; +wea : in std_logic_vector(0 downto 0); +addra : in std_logic_vector(9 downto 0); +dina : in std_logic_vector(7 downto 0); +douta : out std_logic_vector(7 downto 0); +clkb : in std_logic; +web : in std_logic_vector(0 downto 0); +addrb : in std_logic_vector(9 downto 0); +dinb : in std_logic_vector(7 downto 0); +doutb : out std_logic_vector(7 downto 0) +); +end component; + +-- Signals + +-- constant signal set tup to img limits +signal count_col_end : unsigned (9 downto 0); +signal count_row_end : unsigned (9 downto 0); + +-- for storing image rows +signal sel_mem : unsigned (1 downto 0); -- the current memorize row +signal wea_0 : std_logic_vector(0 downto 0); -- we for memorized row 0 +signal wea_1 : std_logic_vector(0 downto 0); -- we for memorized row 1 +signal wea_2 : std_logic_vector(0 downto 0); -- we for memorized row 2 + +signal dina_0 : std_logic_vector(7 downto 0); +signal dina_1 : std_logic_vector(7 downto 0); +signal dina_2 : std_logic_vector(7 downto 0); +signal dina : std_logic_vector(7 downto 0); + +signal addra_w : std_logic_vector(9 downto 0); +signal addra_w_s : unsigned (9 downto 0); +signal wea : std_logic; + + +signal addrb_r : std_logic_vector(9 downto 0); -- addr where to store +signal addrb_r_s : unsigned (9 downto 0); -- addr where to store + +signal doutb_0 : std_logic_vector(7 downto 0); +signal doutb_1 : std_logic_vector(7 downto 0); +signal doutb_2 : std_logic_vector(7 downto 0); + +signal count_row_w : unsigned (10 downto 0); -- row counter while storing +signal store_last_pix : std_logic; -- to be sure that last pixel is stored +signal first_row_w : std_logic; -- '1' when the first row is read so that +-- mem_0 is filled with zeroes +signal all_pix_stored : std_logic; -- '1' when all pixels have been stored + +-- for reading image rows +signal start_read : std_logic; +signal do_read : std_logic; +signal count_row_r : unsigned (10 downto 0); +signal count_row_r_dly : unsigned (10 downto 0); +signal wea_dly : std_logic; +signal end_read : std_logic; + +-- for doing sums +signal do_sum : std_logic; +signal sum1 : unsigned (9 downto 0); +signal sum2 : unsigned (9 downto 0); +signal sum3 : unsigned (9 downto 0); + +-- for doing total +signal do_total : std_logic; +signal sum : unsigned (dsp_in_width-1 downto 0); +signal count_col_total : unsigned (10 downto 0); +signal count_row_total : unsigned (10 downto 0); +signal jump_first_sum : std_logic; + +-- for doing final division +signal do_div : std_logic; +signal do_out : std_logic; +signal end_filter : std_logic; +signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 14564 (=2^17/9) +signal mult_result : unsigned (dsp_out_width-1 downto 0); + + +begin + +img_row_0 : ram_dp_1024x8 +port map ( +clka => @{clk}, +wea => wea_0, +addra => addra_w, +dina => dina_0, +clkb => @{clk}, +web => (others => '0'), +addrb => addrb_r, +dinb => (others => '0'), +doutb => doutb_0 +); +img_row_1 : ram_dp_1024x8 +port map ( +clka => @{clk}, +wea => wea_1, +addra => addra_w, +dina => dina_1, +clkb => @{clk}, +web => (others => '0'), +addrb => addrb_r, +dinb => (others => '0'), +doutb => doutb_1 +); +img_row_2 : ram_dp_1024x8 +port map ( +clka => @{clk}, +wea => wea_2, +addra => addra_w, +dina => dina_2, +clkb => @{clk}, +web => (others => '0'), +addrb => addrb_r, +dinb => (others => '0'), +doutb => doutb_2 +); + + +cst_mult <= to_unsigned(14564, dsp_in_width); +count_col_end <= to_unsigned(img_width-1, 10); +count_row_end <= to_unsigned(img_height-1, 10); + +addra_w <= std_logic_vector(addra_w_s); +addrb_r <= std_logic_vector(addrb_r_s); + +wea_0 <= "1" when ((sel_mem = 0 or first_row_w = '1') and wea = '1') else +"0"; +wea_1 <= "1" when (sel_mem = 1 and wea = '1') else +"0"; +wea_2 <= "1" when (sel_mem = 2 and wea = '1') else +"0"; + +dina_0 <= (others => '0') when (first_row_w = '1') else +dina; + +dina_1 <= dina; +dina_2 <= dina; + +store_row_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +sel_mem <= to_unsigned(0, 2); +addra_w_s <= to_unsigned(img_width-1, 10); +dina <= (others => '0'); + +wea <= '0'; +count_row_w <= to_unsigned(0, 11); + +start_read <= '0'; +first_row_w <= '1'; +store_last_pix <= '0'; +all_pix_stored <= '0'; + +elsif rising_edge(@{clk}) then + +wea <= '0'; +start_read <= '0'; +dina <= (others => '0'); +store_last_pix <= '0'; + +-- @{reset} all when filter has ended +if end_filter = '1' then + +count_row_w <= to_unsigned(0, 11); +sel_mem <= to_unsigned(0, 2); +addra_w_s <= to_unsigned(img_width-1, 10); +first_row_w <= '1'; +all_pix_stored <= '0'; + +elsif store_last_pix = '1' then +addra_w_s <= to_unsigned(0, 10); +-- select next ram +if sel_mem = 2 then +sel_mem <= to_unsigned(0, 2); +else +sel_mem <= sel_mem + 1; +end if; +all_pix_stored <= '1'; -- all pixels are stored + +elsif @{pix_in_enb} = '1' then + +-- prepare to write +wea <= '1'; +-- take input +dina <= @{pix_in}; +-- check if this is the last pixel +if addra_w_s = img_width-2 and count_row_w = img_height then +store_last_pix <= '1'; +end if; +-- if at line end +if addra_w_s = img_width-1 then +-- back to 0 +addra_w_s <= to_unsigned(0, 10); +-- select next ram +if sel_mem = 2 then +sel_mem <= to_unsigned(0, 2); +else +sel_mem <= sel_mem + 1; +end if; +-- end of first line to store +if count_row_w = 1 then +first_row_w <= '0'; +start_read <= '1'; +end if; +count_row_w <= count_row_w + 1; +else +addra_w_s <= addra_w_s + 1; +end if; +end if; +end if; + +end process store_row_process; + +read_rows_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +addrb_r_s <= to_unsigned(0, 10); +do_read <= '0'; +wea_dly <= '0'; + +count_row_r <= to_unsigned(0, 11); +end_read <= '0'; + +do_sum <= '0'; + +elsif rising_edge(@{clk}) then + +wea_dly <= wea; +do_sum <= '0'; +end_read <= '0'; + +if end_read = '1' then +do_sum <= '1'; +end if; + +if start_read = '1' then +do_read <= '1'; + +elsif do_read = '1' and (all_pix_stored = '1' or wea_dly = '1') then + +do_sum <= '1'; +-- whatever the case inc addr if not at end +if addrb_r_s = img_width-1 then +addrb_r_s <= to_unsigned(0, 10); +if count_row_r = img_height-1 then +count_row_r <= to_unsigned(0, 11); +do_read <= '0'; +end_read <= '1'; +else +count_row_r <= count_row_r+1; +end if; +else +addrb_r_s <= addrb_r_s + 1; +end if; +end if; +end if; + +end process read_rows_process; + +sum_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +sum1 <= to_unsigned(0, 10); +sum2 <= to_unsigned(0, 10); +sum3 <= to_unsigned(0, 10); +count_row_r_dly <= to_unsigned(0, 11); +do_total <= '0'; + +elsif rising_edge(@{clk}) then + +do_total <= '0'; +count_row_r_dly <= count_row_r; + +if end_filter = '1' then +sum1 <= to_unsigned(0, 10); +sum2 <= to_unsigned(0, 10); +sum3 <= to_unsigned(0, 10); +end if; +if do_sum = '1' then + +sum3 <= sum2; +sum2 <= sum1; +if count_row_r_dly = img_height-1 then +if sel_mem = 0 then +sum1 <= unsigned("00" & doutb_1) + unsigned("00" & doutb_2); +elsif sel_mem = 1 then +sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_2); +elsif sel_mem = 2 then +sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1); +end if; +else +sum1 <= unsigned("00" & doutb_0) + unsigned("00" & doutb_1) + unsigned("00" & doutb_2); +end if; +do_total <= '1'; +end if; +end if; + +end process sum_process; + +total_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +sum <= to_unsigned(0, dsp_in_width); + +jump_first_sum <= '0'; +count_row_total <= to_unsigned(0, 11); +count_col_total <= to_unsigned(0, 11); +do_div <= '0'; +end_filter <= '0'; + +elsif rising_edge(@{clk}) then + +do_div <= '0'; +end_filter <= '0'; + +if do_total = '1' then + +if jump_first_sum = '1' then +-- sum for the end of the line +if count_col_total = img_width-1 then +sum <= resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width); +count_col_total <= to_unsigned(0, 11); +if count_row_total = img_height-1 then +end_filter <= '1'; +count_row_total <= to_unsigned(0, 11); +jump_first_sum <= '0'; +else +count_row_total <= count_row_total + 1; +end if; +-- sum for the begining of the line +elsif count_col_total = 0 then +sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width); +count_col_total <= to_unsigned(1, 11); +else +sum <= resize(sum1, dsp_in_width) + resize(sum2, dsp_in_width) + resize(sum3, dsp_in_width); +count_col_total <= count_col_total + 1; +end if; +do_div <= '1'; +else +jump_first_sum <= '1'; +end if; +end if; + + +end if; + +end process total_process; + +final_div_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +mult_result <= to_unsigned(0, dsp_out_width); +do_out <= '0'; + +elsif rising_edge(@{clk}) then + +do_out <= '0'; + +if do_div = '1' then +mult_result <= sum * cst_mult; +do_out <= '1'; +end if; +end if; +end process final_div_process; + +@{pix_out} <= std_logic_vector(mult_result(24 downto 17)); +@{pix_out_enb} <= do_out; + +end rtl; + + + + + + + + + + + diff --git a/lib/implementations/checker_impl.xml b/lib/implementations/checker_impl.xml new file mode 100644 index 0000000..2f6167a --- /dev/null +++ b/lib/implementations/checker_impl.xml @@ -0,0 +1,71 @@ + + + + + + + frdfgdr + gre + + + + + + + + +begin + +check_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +@{check_out} <= '0'; +@{data_out} <= (others => '0'); +@{data_out_enb} <= '0'; +@{check_out_enb} <= '0'; + +elsif rising_edge(@{clk}) then + +@{check_out} <= '0'; +@{data_out} <= (others => '0'); +@{data_out_enb} <= '0'; +@{check_out_enb} <= '0'; + +if @{data_in_enb} = '1' then + +@{data_out} <= @{data_in}; +@{data_out_enb} <= '1'; +@{check_out_enb} <= '1'; + +if check_type = 1 then +if unsigned(@{data_in}) <= inf_value then +@{check_out} <= '1'; +end if; +elsif check_type = 2 then +if unsigned(@{data_in}) >= inf_value then +@{check_out} <= '1'; +end if; +elsif check_type = 3 then +if unsigned(@{data_in}) >= inf_value and unsigned(@{data_in}) <= sup_value then +@{check_out} <= '1'; +end if; +end if; +end if; +end if; + +end process check_process; + +end rtl; + + + + + + + + + + + + diff --git a/lib/implementations/csvreader_impl.xml b/lib/implementations/csvreader_impl.xml new file mode 100644 index 0000000..2ea85fe --- /dev/null +++ b/lib/implementations/csvreader_impl.xml @@ -0,0 +1,34 @@ + + + + + + + + This component read data in a CSV file + + + No notes + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/implementations/deserializer_3x1_impl.xml b/lib/implementations/deserializer_3x1_impl.xml new file mode 100644 index 0000000..83971ef --- /dev/null +++ b/lib/implementations/deserializer_3x1_impl.xml @@ -0,0 +1,81 @@ + + + + + + + gre + gre + + + + + + + + +-- Signals +signal do_out : std_logic; +signal data1_reg : std_logic_vector(in_width-1 downto 0); +signal data2_reg : std_logic_vector(in_width-1 downto 0); + +signal count : unsigned(1 downto 0); + +begin + +deser_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +count <= to_unsigned(0, 2); +data1_reg <= (others => '0'); +data2_reg <= (others => '0'); +@{data1_out} <= (others => '0'); +@{data2_out} <= (others => '0'); +@{data3_out} <= (others => '0'); +do_out <= '0'; + +elsif rising_edge(@{clk}) then + +do_out <= '0'; +@{data1_out} <= (others => '0'); +@{data2_out} <= (others => '0'); +@{data3_out} <= (others => '0'); + +if @{data_in_enb} = '1' then + +if count = 0 then +data1_reg <= @{data_in}; +count <= count + 1; +elsif count = 1 then +data2_reg <= @{data_in}; +count <= count + 1; +elsif count = 2 then +@{data1_out} <= data1_reg; +@{data2_out} <= data2_reg; +@{data3_out} <= @{data_in}; +do_out <= '1'; +count <= to_unsigned(0, 2); +end if; +end if; +end if; + +end process deser_process; + +@{data1_out_enb} <= do_out; +@{data2_out_enb} <= do_out; +@{data3_out_enb} <= do_out; + +end rtl; + + + + + + + + + + + + + diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf index 7ae3752..4c1682a 100644 Binary files a/lib/implementations/impls.bmf and b/lib/implementations/impls.bmf differ diff --git a/lib/implementations/logical_AND_3_impl.xml b/lib/implementations/logical_AND_3_impl.xml new file mode 100644 index 0000000..71aedf6 --- /dev/null +++ b/lib/implementations/logical_AND_3_impl.xml @@ -0,0 +1,54 @@ + + + + + + + yt + hyjt + + + + + + + + +begin + +and_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +@{data_out} <= '0'; +@{data_out_enb} <= '0'; + +elsif rising_edge(@{clk}) then + +@{data_out} <= '0'; +@{data_out_enb} <= '0'; + +if @{data1_in_enb} = '1' and @{data2_in_enb} = '1' and @{data3_in_enb} = '1' then + +@{data_out} <= @{data1_in} and @{data2_in} and @{data3_in}; +@{data_out_enb} <= '1'; + +end if; +end if; + +end process and_process; + +end rtl; + + + + + + + + + + + + + diff --git a/rgb3sx8_to_gs_impl.xml b/lib/implementations/rgb3sx8_to_gs_impl.xml similarity index 58% rename from rgb3sx8_to_gs_impl.xml rename to lib/implementations/rgb3sx8_to_gs_impl.xml index 05708e3..4032757 100644 --- a/rgb3sx8_to_gs_impl.xml +++ b/lib/implementations/rgb3sx8_to_gs_impl.xml @@ -1,10 +1,11 @@ - + - - - vcdsv - vrevgfregaqv + + + + fez + fez @@ -25,27 +26,27 @@ begin cst_mult <= to_unsigned(87382, 18); -accum_process : process (clk, reset) +accum_process : process (@{clk}, @{reset}) begin -if reset = '1' then +if @{reset} = '1' then count <= to_unsigned(0, 3); accum <= to_unsigned(0, dsp_in_width); do_mult <= '0'; -elsif rising_edge(clk) then +elsif rising_edge(@{clk}) then do_mult <= '0'; -if rgb_in_enb = '1' then +if @{rgb_in_enb} = '1' then if count = 0 then -accum <= resize(unsigned(rgb_in), dsp_in_width); +accum <= resize(unsigned(@{rgb_in}), dsp_in_width); count <= to_unsigned(1, 3); elsif count = 1 then -accum <= accum + resize(unsigned(rgb_in), dsp_in_width); +accum <= accum + resize(unsigned(@{rgb_in}), dsp_in_width); count <= to_unsigned(2, 3); elsif count = 2 then -accum <= accum + resize(unsigned(rgb_in), dsp_in_width); +accum <= accum + resize(unsigned(@{rgb_in}), dsp_in_width); count <= to_unsigned(0, 3); do_mult <= '1'; end if; @@ -54,12 +55,12 @@ end if; end process accum_process; -mult_process : process (clk, reset) +mult_process : process (@{clk}, @{reset}) begin -if reset = '1' then +if @{reset} = '1' then result <= to_unsigned(0, dsp_out_width); do_out <= '0'; -elsif rising_edge(clk) then +elsif rising_edge(@{clk}) then do_out <= '0'; if do_mult = '1' then @@ -69,18 +70,18 @@ end if; end if; end process mult_process; -gs_out <= std_logic_vector(result(dsp_in_width+7 downto dsp_in_width)); -gs_out_enb <= do_out; +@{gs_out} <= std_logic_vector(result(dsp_in_width+7 downto dsp_in_width)); +@{gs_out_enb} <= do_out; end rtl; - + - + - - + + diff --git a/lib/implementations/rgb3sx8_to_ycbcr_3DSP_impl.xml b/lib/implementations/rgb3sx8_to_ycbcr_3DSP_impl.xml new file mode 100644 index 0000000..3db4b59 --- /dev/null +++ b/lib/implementations/rgb3sx8_to_ycbcr_3DSP_impl.xml @@ -0,0 +1,319 @@ + + + + + + + fez + fez + + + + + + + + +component mult_accum +port ( +@{clk} : in std_logic; +ce : in std_logic; +sclr : in std_logic; +bypass : in std_logic; +a : in std_logic_vector(17 downto 0); +b : in std_logic_vector(17 downto 0); +s : out std_logic_vector(47 downto 0) +); +end component; + +-- Signals +signal do_sum_y : std_logic; +signal do_sum_y_dly : std_logic; +signal do_sum_cr : std_logic; +signal do_sum_cr_dly : std_logic; +signal do_sum_cb : std_logic; +signal do_sum_cb_dly : std_logic; +signal do_out : std_logic; +signal do_out_cr : std_logic; +signal do_out_cb : std_logic; +signal do_out_y : std_logic; +signal count_y : unsigned (2 downto 0); +signal count_cr : unsigned (2 downto 0); +signal count_cb : unsigned (2 downto 0); +signal y : signed(8 downto 0); +signal y_dly1 : signed(8 downto 0); +signal y_dly2 : signed(8 downto 0); +signal cb : signed(8 downto 0); +signal cb_dly1 : signed(8 downto 0); +signal cr : signed(8 downto 0); +signal cst_y_r : signed(17 downto 0); +signal cst_y_g : signed(17 downto 0); +signal cst_y_b : signed(17 downto 0); +signal cst_cb_r : signed(17 downto 0); +signal cst_cb_g : signed(17 downto 0); +signal cst_cb_b : signed(17 downto 0); +signal cst_cr_r : signed(17 downto 0); +signal cst_cr_g : signed(17 downto 0); +signal cst_cr_b : signed(17 downto 0); + +signal bypass_y : std_logic; +signal a_y : std_logic_vector(17 downto 0); +signal b_y : std_logic_vector(17 downto 0); +signal s_y : std_logic_vector(47 downto 0); +signal bypass_cr : std_logic; +signal a_cr : std_logic_vector(17 downto 0); +signal b_cr : std_logic_vector(17 downto 0); +signal s_cr : std_logic_vector(47 downto 0); +signal bypass_cb : std_logic; +signal a_cb : std_logic_vector(17 downto 0); +signal b_cb : std_logic_vector(17 downto 0); +signal s_cb : std_logic_vector(47 downto 0); + +signal compo_out : std_logic_vector(7 downto 0); + +begin + +y_multiplier : mult_accum +port map ( +@{clk} => @{clk}, +ce => '1', +sclr => '0', +bypass => bypass_y, +a => a_y, +b => b_y, +s => s_y +); +cr_multiplier : mult_accum +port map ( +@{clk} => @{clk}, +ce => '1', +sclr => '0', +bypass => bypass_cr, +a => a_cr, +b => b_cr, +s => s_cr +); +cb_multiplier : mult_accum +port map ( +@{clk} => @{clk}, +ce => '1', +sclr => '0', +bypass => bypass_cb, +a => a_cb, +b => b_cb, +s => s_cb +); + + +cst_y_r <= to_signed(33658, 18); +cst_y_g <= to_signed(66077, 18); +cst_y_b <= to_signed(12833, 18); +cst_cb_r <= to_signed(-19428, 18); +cst_cb_g <= to_signed(-38141, 18); +cst_cb_b <= to_signed(57569, 18); +cst_cr_r <= to_signed(57569, 18); +cst_cr_g <= to_signed(-48207, 18); +cst_cr_b <= to_signed(-9362, 18); + +multy_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +a_y <= (others => '0'); +b_y <= (others => '0'); + +count_y <= to_unsigned(0, 3); +do_sum_y <= '0'; + +elsif rising_edge(@{clk}) then + +do_sum_y <= '0'; + +a_y <= (others => '0'); +b_y <= (others => '0'); + +if @{rgb_in_enb} = '1' then + +a_y <= "0000000000" & @{rgb_in}; + +if count_y = 0 then +b_y <= std_logic_vector(cst_y_b); + +count_y <= to_unsigned(1, 3); + +elsif count_y = 1 then +b_y <= std_logic_vector(cst_y_g); +count_y <= to_unsigned(2, 3); + +elsif count_y = 2 then +b_y <= std_logic_vector(cst_y_r); +count_y <= to_unsigned(0, 3); +do_sum_y <= '1'; +end if; +end if; +end if; +end process multy_process; + +sumy_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +bypass_y <= '0'; +y <= to_signed(0, 9); +y_dly1 <= to_signed(0, 9); +y_dly2 <= to_signed(0, 9); + +elsif rising_edge(@{clk}) then +bypass_y <= do_sum_y; +do_sum_y_dly <= do_sum_y; +y_dly1 <= y; +y_dly2 <= y_dly1; + +if do_sum_y_dly = '1' then +y <= to_signed(16, 9) + signed(s_y(25 downto 17)); +end if; +end if; + +end process sumy_process; + +multcb_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +a_cb <= (others => '0'); +b_cb <= (others => '0'); + +count_cb <= to_unsigned(0, 3); +do_sum_cb <= '0'; + +elsif rising_edge(@{clk}) then + +do_sum_cb <= '0'; + +a_cb <= (others => '0'); +b_cb <= (others => '0'); + +if @{rgb_in_enb} = '1' then + +a_cb <= "0000000000" & @{rgb_in}; + +if count_cb = 0 then +b_cb <= std_logic_vector(cst_cb_b); + +count_cb <= to_unsigned(1, 3); + +elsif count_cb = 1 then +b_cb <= std_logic_vector(cst_cb_g); +count_cb <= to_unsigned(2, 3); + +elsif count_cb = 2 then +b_cb <= std_logic_vector(cst_cb_r); +count_cb <= to_unsigned(0, 3); +do_sum_cb <= '1'; +end if; +end if; +end if; +end process multcb_process; + +sumcb_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +bypass_cb <= '0'; +cb <= to_signed(0, 9); +cb_dly1 <= to_signed(0, 9); +elsif rising_edge(@{clk}) then +bypass_cb <= do_sum_cb; +do_sum_cb_dly <= do_sum_cb; +cb_dly1 <= cb; + +if do_sum_cb_dly = '1' then +cb <= to_signed(128, 9) + signed(s_cb(25 downto 17)); +end if; +end if; + +end process sumcb_process; + +multcr_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +a_cr <= (others => '0'); +b_cr <= (others => '0'); + +count_cr <= to_unsigned(0, 3); +do_sum_cr <= '0'; + +elsif rising_edge(@{clk}) then + +do_sum_cr <= '0'; + +a_cr <= (others => '0'); +b_cr <= (others => '0'); + +if @{rgb_in_enb} = '1' then + +a_cr <= "0000000000" & @{rgb_in}; + +if count_cr = 0 then +b_cr <= std_logic_vector(cst_cr_b); + +count_cr <= to_unsigned(1, 3); + +elsif count_cr = 1 then +b_cr <= std_logic_vector(cst_cr_g); +count_cr <= to_unsigned(2, 3); + +elsif count_cr = 2 then +b_cr <= std_logic_vector(cst_cr_r); +count_cr <= to_unsigned(0, 3); +do_sum_cr <= '1'; +end if; +end if; +end if; +end process multcr_process; + +sumcr_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +bypass_cr <= '0'; +cr <= to_signed(0, 9); +do_out_cr <= '0'; + +elsif rising_edge(@{clk}) then +bypass_cr <= do_sum_cr; +do_sum_cr_dly <= do_sum_cr; +do_out_cr <= '0'; + +if do_sum_cr_dly = '1' then +do_out_cr <= '1'; +cr <= to_signed(128, 9) + signed(s_cr(25 downto 17)); +end if; +end if; +end process sumcr_process; + +out_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then +do_out_y <= '0'; +do_out_cb <= '0'; +elsif rising_edge(@{clk}) then +do_out_cb <= do_out_cr; +do_out_y <= do_out_cb; +end if; +end process out_process; + + +@{ycbcr_out} <= std_logic_vector(y_dly2(7 downto 0)) when do_out_y = '1' else +std_logic_vector(cb_dly1(7 downto 0)) when do_out_cb = '1' else +std_logic_vector(cr(7 downto 0)) when do_out_cr = '1' else +(others => '0'); +@{ycbcr_out_enb} <= do_out_y or do_out_cb or do_out_cr; + +end rtl; + + + + + + + + + + + diff --git a/lib/implementations/threshold_extctl_impl.xml b/lib/implementations/threshold_extctl_impl.xml new file mode 100644 index 0000000..a136203 --- /dev/null +++ b/lib/implementations/threshold_extctl_impl.xml @@ -0,0 +1,59 @@ + + + + + + + fez + fez + + + + + + + + +-- Signals +signal def_val : unsigned(in_width-1 downto 0); + +begin + +def_val <= to_unsigned(default_value, in_width); + +threshold_process : process (@{clk}, @{reset}) +begin +if @{reset} = '1' then + +@{data_out_enb} <= '0'; +@{data_out} <= (others => '0'); + +elsif rising_edge(@{clk}) then + +@{data_out_enb} <= '0'; + +if @{data_in_enb} = '1' and @{keep_in_enb} = '1' then + +if @{keep_in} = '1' then +@{data_out} <= @{data_in}; +else +@{data_out} <= std_logic_vector(def_val); +end if; +@{data_out_enb} <= '1'; +end if; +end if; +end process threshold_process; + +end rtl; + + + + + + + + + + + + diff --git a/lib/references/boxfilter_3x3.xml b/lib/references/boxfilter_3x3.xml new file mode 100644 index 0000000..5e163ad --- /dev/null +++ b/lib/references/boxfilter_3x3.xml @@ -0,0 +1,29 @@ + + + + boxfilter_3x3 + + + frdfgdr + gregre + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/checker.xml b/lib/references/checker.xml new file mode 100644 index 0000000..6934164 --- /dev/null +++ b/lib/references/checker.xml @@ -0,0 +1,31 @@ + + + + checker + + + gre + gre + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/csvreader.xml b/lib/references/csvreader.xml new file mode 100644 index 0000000..d22ab09 --- /dev/null +++ b/lib/references/csvreader.xml @@ -0,0 +1,39 @@ + + + + + generator-csvreader + + + + + generates data from a csv file + + + generates data from a csv file + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/deserializer_3x1.xml b/lib/references/deserializer_3x1.xml new file mode 100644 index 0000000..874ecad --- /dev/null +++ b/lib/references/deserializer_3x1.xml @@ -0,0 +1,30 @@ + + + + deserializer_3x1 + + + gre + gre + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/logical_AND_3.xml b/lib/references/logical_AND_3.xml new file mode 100644 index 0000000..99b4aea --- /dev/null +++ b/lib/references/logical_AND_3.xml @@ -0,0 +1,28 @@ + + + + logical_AND_3 + + + yt + hyjt + + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/references.bmf b/lib/references/references.bmf index 8ec5506..b01fb7c 100644 Binary files a/lib/references/references.bmf and b/lib/references/references.bmf differ diff --git a/lib/references/rgb3sx8_to_gs.xml b/lib/references/rgb3sx8_to_gs.xml new file mode 100644 index 0000000..9271adc --- /dev/null +++ b/lib/references/rgb3sx8_to_gs.xml @@ -0,0 +1,27 @@ + + + + rgb3sx8_to_gs + + + fez + fez + + + + + + + + + + + + + + + + + + + diff --git a/lib/references/rgb3sx8_to_ycbcr_3DSP.xml b/lib/references/rgb3sx8_to_ycbcr_3DSP.xml new file mode 100644 index 0000000..5bbc856 --- /dev/null +++ b/lib/references/rgb3sx8_to_ycbcr_3DSP.xml @@ -0,0 +1,24 @@ + + + + rgb3sx8_to_ycbcr_3DSP + + + fez + fez + + + + + + + + + + + + + + + + diff --git a/lib/references/threshold_extctl.xml b/lib/references/threshold_extctl.xml new file mode 100644 index 0000000..136226f --- /dev/null +++ b/lib/references/threshold_extctl.xml @@ -0,0 +1,29 @@ + + + + threshold_extctl + + + fez + fez + + + + + + + + + + + + + + + + + + + + + diff --git a/logical_AND_3.vhd b/logical_AND_3.vhd new file mode 100644 index 0000000..720b733 --- /dev/null +++ b/logical_AND_3.vhd @@ -0,0 +1,65 @@ +------------------------------------------------------------------------------- +-- +-- File : logical_AND_3.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a logical AND on three inputs. +-- +-- +-- Note : +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity logical_AND_3 is + port( + clk : in std_logic; + reset : in std_logic; + data1_in : in std_logic; + data1_in_enb : in std_logic; + data2_in : in std_logic; + data2_in_enb : in std_logic; + data3_in : in std_logic; + data3_in_enb : in std_logic; + + data_out : out std_logic; + data_out_enb : out std_logic -- the control signal, common to all output + ); +end logical_AND_3; + + +architecture rtl of logical_AND_3 is + +begin + + and_process : process (clk, reset) + begin + if reset = '1' then + + data_out <= '0'; + data_out_enb <= '0'; + + elsif rising_edge(clk) then + + data_out <= '0'; + data_out_enb <= '0'; + + if data1_in_enb = '1' and data2_in_enb = '1' and data3_in_enb = '1' then + + data_out <= data1_in and data2_in and data3_in; + data_out_enb <= '1'; + + end if; + end if; + + end process and_process; + +end rtl; + diff --git a/object-files.txt b/object-files.txt index 47af6ad..9a90873 100644 --- a/object-files.txt +++ b/object-files.txt @@ -7,6 +7,8 @@ COMMON-OBJ = $(BUILDPATH)/AbstractBlock.o \ $(BUILDPATH)/FunctionalInterface.o \ $(BUILDPATH)/GroupInterface.o \ $(BUILDPATH)/ReferenceInterface.o \ + $(BUILDPATH)/AbstractInputModifier.o \ + $(BUILDPATH)/DelayInputModifier.o \ $(BUILDPATH)/BlockImplementation.o \ $(BUILDPATH)/Graph.o \ $(BUILDPATH)/AbstractBoxItem.o \ diff --git a/projectfile.xsd b/projectfile.xsd index 811beb2..de6ec42 100644 --- a/projectfile.xsd +++ b/projectfile.xsd @@ -98,6 +98,12 @@ + + + + + + @@ -223,6 +229,7 @@ + @@ -230,7 +237,8 @@ - + + @@ -438,6 +446,20 @@ + + + + + + + + + + + + + + diff --git a/reference.xsd b/reference.xsd index b219bfa..29f5d28 100644 --- a/reference.xsd +++ b/reference.xsd @@ -19,6 +19,7 @@ + @@ -47,6 +48,13 @@ + + + + + + + @@ -207,9 +215,10 @@ - - - + + + + diff --git a/rgb3sx8_to_gs.vhd b/rgb3sx8_to_gs.vhd new file mode 100644 index 0000000..06abc7b --- /dev/null +++ b/rgb3sx8_to_gs.vhd @@ -0,0 +1,102 @@ +------------------------------------------------------------------------------- +-- +-- File : rgb3sx8_to_gs.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a conversion from rgb24 (8 bits/serial) to grayscale +-- +-- Note : rgb24 (8 bits/serial) pixels are composed of three 8 bits +-- values that are consumed on port rgb_in, in the following +-- order : blue, green, red. +-- output value on gs_out is computed with (red+green+blue)/3 +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity rgb3sx8_to_gs is + generic( + dsp_in_width : natural := 18; + dsp_out_width : natural := 36 + ); + port( + clk : in std_logic; + reset : in std_logic; + rgb_in : in std_logic_vector(7 downto 0); + rgb_in_enb : in std_logic; + gs_out : out std_logic_vector(7 downto 0); + gs_out_enb : out std_logic + + ); +end rgb3sx8_to_gs; + + +architecture rtl of rgb3sx8_to_gs is + + -- Signals + signal do_mult : std_logic; + signal do_out : std_logic; + signal count : unsigned (2 downto 0); + signal accum : unsigned(dsp_in_width-1 downto 0); + signal result : unsigned(dsp_out_width-1 downto 0); + signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 87382 to do /3 + +begin + + cst_mult <= to_unsigned(87382, 18); + + accum_process : process (clk, reset) + begin + if reset = '1' then + count <= to_unsigned(0, 3); + accum <= to_unsigned(0, dsp_in_width); + do_mult <= '0'; + + elsif rising_edge(clk) then + + do_mult <= '0'; + + if rgb_in_enb = '1' then + + if count = 0 then + accum <= resize(unsigned(rgb_in), dsp_in_width); + count <= to_unsigned(1, 3); + elsif count = 1 then + accum <= accum + resize(unsigned(rgb_in), dsp_in_width); + count <= to_unsigned(2, 3); + elsif count = 2 then + accum <= accum + resize(unsigned(rgb_in), dsp_in_width); + count <= to_unsigned(0, 3); + do_mult <= '1'; + end if; + end if; + end if; + + end process accum_process; + + mult_process : process (clk, reset) + begin + if reset = '1' then + result <= to_unsigned(0, dsp_out_width); + do_out <= '0'; + elsif rising_edge(clk) then + + do_out <= '0'; + if do_mult = '1' then + result <= accum * cst_mult; + do_out <= '1'; + end if; + end if; + end process mult_process; + + gs_out <= std_logic_vector(result(dsp_in_width+7 downto dsp_in_width)); + gs_out_enb <= do_out; + +end rtl; + diff --git a/rgb3sx8_to_gs.xml b/rgb3sx8_to_gs.xml deleted file mode 100644 index d9583a1..0000000 --- a/rgb3sx8_to_gs.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - rgb3sx8_to_gs - - - vcdsv - vrevgfregaqv - - - - - - - - - - - - - - - - - - - diff --git a/rgb3sx8_to_ycbcr_3DSP.vhd b/rgb3sx8_to_ycbcr_3DSP.vhd new file mode 100644 index 0000000..c2320fe --- /dev/null +++ b/rgb3sx8_to_ycbcr_3DSP.vhd @@ -0,0 +1,337 @@ +------------------------------------------------------------------------------- +-- +-- File : rgb3sx8_to_ycbcr_3DSP.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a conversion from rgb24 (8 bits/serial) to YCrCb +-- +-- Note : rgb24 (8 bits/serial) pixels are composed of three 8 bits +-- values that are consumed on port rgb_in, in the following +-- order : blue, green, red. +-- output values on ycrcb_out are produced in the following +-- order: cb, cr, y +-- They are computed using ITU-R BT.601 conversion principles, +-- assuming that RGB component are digital and thus rangin +-- from 0 to 255. Formulas are: +-- Y = 16 + 65.738R/256 + 129.057G/256 + 25.064B/256 +-- Cb = 128 - 37.945R/256 - 74.494G/256 + 112.439B/256 +-- Cr = 128 + 112.439R/256 - 94.154G/256 - 18.285B/256 +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity rgb3sx8_to_ycbcr_3DSP is + port( + clk : in std_logic; + reset : in std_logic; + rgb_in : in std_logic_vector(7 downto 0); + rgb_in_enb : in std_logic; + ycbcr_out : out std_logic_vector(7 downto 0); + ycbcr_out_enb : out std_logic + + ); +end rgb3sx8_to_ycbcr_3DSP; + + +architecture rtl of rgb3sx8_to_ycbcr_3DSP is + + component mult_accum + port ( + clk : in std_logic; + ce : in std_logic; + sclr : in std_logic; + bypass : in std_logic; + a : in std_logic_vector(17 downto 0); + b : in std_logic_vector(17 downto 0); + s : out std_logic_vector(47 downto 0) + ); + end component; + +-- Signals + signal do_sum_y : std_logic; + signal do_sum_y_dly : std_logic; + signal do_sum_cr : std_logic; + signal do_sum_cr_dly : std_logic; + signal do_sum_cb : std_logic; + signal do_sum_cb_dly : std_logic; + signal do_out : std_logic; + signal do_out_cr : std_logic; + signal do_out_cb : std_logic; + signal do_out_y : std_logic; + signal count_y : unsigned (2 downto 0); + signal count_cr : unsigned (2 downto 0); + signal count_cb : unsigned (2 downto 0); + signal y : signed(8 downto 0); + signal y_dly1 : signed(8 downto 0); + signal y_dly2 : signed(8 downto 0); + signal cb : signed(8 downto 0); + signal cb_dly1 : signed(8 downto 0); + signal cr : signed(8 downto 0); + signal cst_y_r : signed(17 downto 0); + signal cst_y_g : signed(17 downto 0); + signal cst_y_b : signed(17 downto 0); + signal cst_cb_r : signed(17 downto 0); + signal cst_cb_g : signed(17 downto 0); + signal cst_cb_b : signed(17 downto 0); + signal cst_cr_r : signed(17 downto 0); + signal cst_cr_g : signed(17 downto 0); + signal cst_cr_b : signed(17 downto 0); + + signal bypass_y : std_logic; + signal a_y : std_logic_vector(17 downto 0); + signal b_y : std_logic_vector(17 downto 0); + signal s_y : std_logic_vector(47 downto 0); + signal bypass_cr : std_logic; + signal a_cr : std_logic_vector(17 downto 0); + signal b_cr : std_logic_vector(17 downto 0); + signal s_cr : std_logic_vector(47 downto 0); + signal bypass_cb : std_logic; + signal a_cb : std_logic_vector(17 downto 0); + signal b_cb : std_logic_vector(17 downto 0); + signal s_cb : std_logic_vector(47 downto 0); + + signal compo_out : std_logic_vector(7 downto 0); + +begin + + y_multiplier : mult_accum + port map ( + clk => clk, + ce => '1', + sclr => '0', + bypass => bypass_y, + a => a_y, + b => b_y, + s => s_y + ); + cr_multiplier : mult_accum + port map ( + clk => clk, + ce => '1', + sclr => '0', + bypass => bypass_cr, + a => a_cr, + b => b_cr, + s => s_cr + ); + cb_multiplier : mult_accum + port map ( + clk => clk, + ce => '1', + sclr => '0', + bypass => bypass_cb, + a => a_cb, + b => b_cb, + s => s_cb + ); + + + cst_y_r <= to_signed(33658, 18); + cst_y_g <= to_signed(66077, 18); + cst_y_b <= to_signed(12833, 18); + cst_cb_r <= to_signed(-19428, 18); + cst_cb_g <= to_signed(-38141, 18); + cst_cb_b <= to_signed(57569, 18); + cst_cr_r <= to_signed(57569, 18); + cst_cr_g <= to_signed(-48207, 18); + cst_cr_b <= to_signed(-9362, 18); + + multy_process : process (clk, reset) + begin + if reset = '1' then + a_y <= (others => '0'); + b_y <= (others => '0'); + + count_y <= to_unsigned(0, 3); + do_sum_y <= '0'; + + elsif rising_edge(clk) then + + do_sum_y <= '0'; + + a_y <= (others => '0'); + b_y <= (others => '0'); + + if rgb_in_enb = '1' then + + a_y <= "0000000000" & rgb_in; + + if count_y = 0 then + b_y <= std_logic_vector(cst_y_b); + + count_y <= to_unsigned(1, 3); + + elsif count_y = 1 then + b_y <= std_logic_vector(cst_y_g); + count_y <= to_unsigned(2, 3); + + elsif count_y = 2 then + b_y <= std_logic_vector(cst_y_r); + count_y <= to_unsigned(0, 3); + do_sum_y <= '1'; + end if; + end if; + end if; + end process multy_process; + + sumy_process : process (clk, reset) + begin + if reset = '1' then + bypass_y <= '0'; + y <= to_signed(0, 9); + y_dly1 <= to_signed(0, 9); + y_dly2 <= to_signed(0, 9); + + elsif rising_edge(clk) then + bypass_y <= do_sum_y; + do_sum_y_dly <= do_sum_y; + y_dly1 <= y; + y_dly2 <= y_dly1; + + if do_sum_y_dly = '1' then + y <= to_signed(16, 9) + signed(s_y(25 downto 17)); + end if; + end if; + + end process sumy_process; + + multcb_process : process (clk, reset) + begin + if reset = '1' then + a_cb <= (others => '0'); + b_cb <= (others => '0'); + + count_cb <= to_unsigned(0, 3); + do_sum_cb <= '0'; + + elsif rising_edge(clk) then + + do_sum_cb <= '0'; + + a_cb <= (others => '0'); + b_cb <= (others => '0'); + + if rgb_in_enb = '1' then + + a_cb <= "0000000000" & rgb_in; + + if count_cb = 0 then + b_cb <= std_logic_vector(cst_cb_b); + + count_cb <= to_unsigned(1, 3); + + elsif count_cb = 1 then + b_cb <= std_logic_vector(cst_cb_g); + count_cb <= to_unsigned(2, 3); + + elsif count_cb = 2 then + b_cb <= std_logic_vector(cst_cb_r); + count_cb <= to_unsigned(0, 3); + do_sum_cb <= '1'; + end if; + end if; + end if; + end process multcb_process; + + sumcb_process : process (clk, reset) + begin + if reset = '1' then + bypass_cb <= '0'; + cb <= to_signed(0, 9); + cb_dly1 <= to_signed(0, 9); + elsif rising_edge(clk) then + bypass_cb <= do_sum_cb; + do_sum_cb_dly <= do_sum_cb; + cb_dly1 <= cb; + + if do_sum_cb_dly = '1' then + cb <= to_signed(128, 9) + signed(s_cb(25 downto 17)); + end if; + end if; + + end process sumcb_process; + + multcr_process : process (clk, reset) + begin + if reset = '1' then + a_cr <= (others => '0'); + b_cr <= (others => '0'); + + count_cr <= to_unsigned(0, 3); + do_sum_cr <= '0'; + + elsif rising_edge(clk) then + + do_sum_cr <= '0'; + + a_cr <= (others => '0'); + b_cr <= (others => '0'); + + if rgb_in_enb = '1' then + + a_cr <= "0000000000" & rgb_in; + + if count_cr = 0 then + b_cr <= std_logic_vector(cst_cr_b); + + count_cr <= to_unsigned(1, 3); + + elsif count_cr = 1 then + b_cr <= std_logic_vector(cst_cr_g); + count_cr <= to_unsigned(2, 3); + + elsif count_cr = 2 then + b_cr <= std_logic_vector(cst_cr_r); + count_cr <= to_unsigned(0, 3); + do_sum_cr <= '1'; + end if; + end if; + end if; + end process multcr_process; + + sumcr_process : process (clk, reset) + begin + if reset = '1' then + bypass_cr <= '0'; + cr <= to_signed(0, 9); + do_out_cr <= '0'; + + elsif rising_edge(clk) then + bypass_cr <= do_sum_cr; + do_sum_cr_dly <= do_sum_cr; + do_out_cr <= '0'; + + if do_sum_cr_dly = '1' then + do_out_cr <= '1'; + cr <= to_signed(128, 9) + signed(s_cr(25 downto 17)); + end if; + end if; + end process sumcr_process; + + out_process : process (clk, reset) + begin + if reset = '1' then + do_out_y <= '0'; + do_out_cb <= '0'; + elsif rising_edge(clk) then + do_out_cb <= do_out_cr; + do_out_y <= do_out_cb; + end if; + end process out_process; + + + ycbcr_out <= std_logic_vector(y_dly2(7 downto 0)) when do_out_y = '1' else + std_logic_vector(cb_dly1(7 downto 0)) when do_out_cb = '1' else + std_logic_vector(cr(7 downto 0)) when do_out_cr = '1' else + (others => '0'); + ycbcr_out_enb <= do_out_y or do_out_cb or do_out_cr; + +end rtl; + diff --git a/threshold_extctl.vhd b/threshold_extctl.vhd new file mode 100644 index 0000000..90daeae --- /dev/null +++ b/threshold_extctl.vhd @@ -0,0 +1,77 @@ +------------------------------------------------------------------------------- +-- +-- File : threshold _extctl.vhd +-- Related files : +-- +-- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) +-- +-- Creation Date : 2017/10/16 +-- +-- Description : This IP does a threshold based on a external signal +-- +-- +-- Note : input data is kept as is depending on the fact that +-- the keep_in signal is asserted to 1 or not. It it is not, +-- then input is replaced by the default_value given as a +-- generic. Note that keep_in_enb and data_in_enb must be +-- asserted to 1 at the same time so that the block gives an output +-- +------------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +entity threshold_extctl is + generic( + in_width : natural := 8; + default_value : natural := 0 + ); + port( + clk : in std_logic; + reset : in std_logic; + data_in : in std_logic_vector(in_width-1 downto 0); + data_in_enb : in std_logic; + keep_in : in std_logic; + keep_in_enb : in std_logic; + data_out : out std_logic_vector(in_width-1 downto 0); + data_out_enb : out std_logic + + ); +end threshold_extctl; + + +architecture rtl of threshold_extctl is + + -- Signals + signal def_val : unsigned(in_width-1 downto 0); + +begin + + def_val <= to_unsigned(default_value, in_width); + + threshold_process : process (clk, reset) + begin + if reset = '1' then + + data_out_enb <= '0'; + data_out <= (others => '0'); + + elsif rising_edge(clk) then + + data_out_enb <= '0'; + + if data_in_enb = '1' and keep_in_enb = '1' then + + if keep_in = '1' then + data_out <= data_in; + else + data_out <= std_logic_vector(def_val); + end if; + data_out_enb <= '1'; + end if; + end if; + end process threshold_process; + +end rtl; + diff --git a/toto.xml b/toto.xml deleted file mode 100644 index 90db6c9..0000000 --- a/toto.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -