From: stephane Domas Date: Tue, 15 May 2018 17:43:56 +0000 (+0200) Subject: finished testbench generation X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain finished testbench generation --- diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp index 218ea61..de28272 100644 --- a/AbstractBlock.cpp +++ b/AbstractBlock.cpp @@ -76,8 +76,10 @@ bool AbstractBlock::isStimuliBlock() { * and has at least one data output. * By the way, blocks that have no data input/output * (like clkrstgen) are not sources ! + * A source may also be a block of special type source. */ bool AbstractBlock::isSourceBlock() { + if (specialType == Source) return true; if (getDataInputs().size() > 0) return false; if (getDataOutputs().size() == 0) return false; return true; diff --git a/AbstractBlock.h b/AbstractBlock.h index efbd474..f40af86 100644 --- a/AbstractBlock.h +++ b/AbstractBlock.h @@ -75,7 +75,7 @@ public: virtual bool isGroupBlock(); virtual bool isStimuliBlock(); //! a stimuli block is outside the top group and simulates a peripheral (NB: this is also a source) virtual bool isTopGroupBlock(); - bool isSourceBlock(); //! a source block has no data inputs and thus executes infinitely + bool isSourceBlock(); //! a source block is either a block that has no data inputs or that is of special type source. Thus it executes infinitely bool isSinkBlock(); //! a sink block has no data outputs and just collects what it receives (i.e. no compatibility check) bool isWBConfigurable(); diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp index 3fdd87a..83aa4c3 100644 --- a/AbstractInterface.cpp +++ b/AbstractInterface.cpp @@ -14,8 +14,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner) { type = Boolean; endianess = LittleEndian; associatedIface = NULL; - clkIface = ""; - clkIfaceType = 0; + clkIfaceName = ""; + clkIfaceType = NoName; } @@ -29,8 +29,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name type = typeFromString(_type); endianess = _endianess; associatedIface = NULL; - clkIface = ""; - clkIfaceType = 0; + clkIfaceName = ""; + clkIfaceType = NoName; } AbstractInterface::AbstractInterface(AbstractInterface* other) { @@ -42,7 +42,7 @@ AbstractInterface::AbstractInterface(AbstractInterface* other) { purpose = other->purpose; endianess = LittleEndian; associatedIface = NULL; - clkIface = other->clkIface; + clkIfaceName = other->clkIfaceName; clkIfaceType = other->clkIfaceType; } @@ -216,7 +216,7 @@ bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) { AbstractInterface* AbstractInterface::getClockIface() { if (clkIfaceType == ClockName) { - return owner->getIfaceFromName(clkIface); + return owner->getIfaceFromName(clkIfaceName); } return NULL; } @@ -227,7 +227,7 @@ double AbstractInterface::getClockFrequency() throw(Exception) { int idClock = -1; if (clkIfaceType == ParameterName) { - BlockParameter* param = owner->getParameterFromName(clkIface); + BlockParameter* param = owner->getParameterFromName(clkIfaceName); if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this)); bool ok; double freq = param->getDoubleValue(&ok); @@ -247,46 +247,6 @@ double AbstractInterface::getClockFrequency() throw(Exception) { } -bool AbstractInterface::setClockIface(QString name) { - /* 2 cases : - * - this is a Data interface - * - this is a Clock output (from a clkrstgen) - * - * iface must correspond to an existing clock interface name - * or a user parameter prepend with a $. - */ - if ((purpose == Data) || ((purpose == Clock) && (direction == Output))) { - if (name.at(0) == '$') { - name.remove(0,1); - QList params = owner->getUserParameters(); - foreach(BlockParameter* p, params) { - if (p->getName() == name) { - clkIface = name; - clkIfaceType = ParameterName; - return true; - } - } - // error case: cannot found the input clock - return false; - } - else { - QList clocks = owner->getInterfaces(Input, Clock); - foreach(AbstractInterface* iface, clocks) { - if (iface->getName() == name) { - clkIface = name; - clkIfaceType = ClockName; - return true; - } - } - // error case: cannot found the user paramter - return false; - } - } - clkIface = ""; - clkIfaceType = NoName; - return true; -} - int AbstractInterface::getIntDirection(QString str) { if(str == "input") return Input; @@ -351,7 +311,10 @@ QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exc //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl; if (context == Instance) { - if (direction == Output) { + if (direction == Input) { + ret = owner->getName()+"_"+name; + } + else if (direction == Output) { ret = "from_"+owner->getName()+"_"+name; } else if (direction == InOut) { diff --git a/AbstractInterface.h b/AbstractInterface.h index 832fe48..0ad387a 100644 --- a/AbstractInterface.h +++ b/AbstractInterface.h @@ -30,7 +30,7 @@ public : enum IfaceDirection { AnyDirection = 0, Input = 1, Output = 2, InOut = 3 }; enum IfaceVHDLContext {AnyContext = 0, Entity = 1, Component = 2, Instance = 3, Signal = 4 }; enum IfaceVHDLFlags { NoComma = 1 }; - enum IfaceClockName { NoName = 0, ClockName, ParameterName }; + enum IfaceClockName { NoName = 0, ClockName, ParameterName, InheritedName }; static int getIntDirection(QString str); static int getIntPurpose(QString str); @@ -54,7 +54,7 @@ public : QString getDirectionString(); inline AbstractBlock *getOwner() { return owner;} inline AbstractInterface* getAssociatedIface() { return associatedIface; } - inline QString getClockIfaceString() { return clkIface; } + inline QString getClockIfaceString() { return clkIfaceName; } inline int getClockIfaceType() { return clkIfaceType; } AbstractInterface* getClockIface(); virtual int getClockDomain() throw(Exception) = 0; // determine on which clock domain is sync this interface @@ -71,7 +71,8 @@ public : void setPurpose(int _purpose); void setDirection(int _direction); bool setAssociatedIface(AbstractInterface* iface); - bool setClockIface(QString name); + inline void setClockIfaceType(int type) { clkIfaceType = type; } + inline void setClockIfaceName(QString name) { clkIfaceName = name; } // testers virtual bool isReferenceInterface(); @@ -112,7 +113,7 @@ protected: * Nevertheless, the designer has the possibility to connect the block taht owns this interface to another clkrstgen block. Moreover, * some blocks may have several clocks, e.g. dual port RAMs, FIFOs. */ - QString clkIface; + QString clkIfaceName; int clkIfaceType; // 0 for not affected, 1 for clock input name, 2 for user param name diff --git a/BlockParameterGeneric.cpp b/BlockParameterGeneric.cpp index 14b8c59..4ba6c8e 100644 --- a/BlockParameterGeneric.cpp +++ b/BlockParameterGeneric.cpp @@ -75,6 +75,20 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { ret = formatNoValue.arg(name).arg(typeStr); } } + else if (type == String) { + typeStr = "string"; + if (!userValue.isNull()) { + valueStr = "\""+userValue.toString()+"\""; + ret = formatValue.arg(name).arg(typeStr).arg(valueStr); + } + else if (!defaultValue.isNull()) { + valueStr = "\""+defaultValue.toString()+"\""; + ret = formatValue.arg(name).arg(typeStr).arg(valueStr); + } + else { + ret = formatNoValue.arg(name).arg(typeStr); + } + } else { typeStr = getTypeString(); if (!userValue.isNull()) { @@ -109,6 +123,9 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { if ((type == Boolean)||(type == Bit)) { ret = format.arg(name).arg("'"+userValue.toString()+"'"); } + else if (type == String) { + ret = format.arg(name).arg("\""+userValue.toString()+"\""); + } else { ret = format.arg(name).arg(userValue.toString()); } @@ -117,6 +134,9 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) { if ((type == Boolean)||(type == Bit)) { ret = format.arg(name).arg("'"+defaultValue.toString()+"'"); } + else if (type == String) { + ret = format.arg(name).arg("\""+defaultValue.toString()+"\""); + } else { ret = format.arg(name).arg(defaultValue.toString()); } diff --git a/ConnectedInterface.h b/ConnectedInterface.h index c9e03e8..e3dbfd3 100644 --- a/ConnectedInterface.h +++ b/ConnectedInterface.h @@ -42,8 +42,8 @@ public : 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; + virtual bool canConnectTo(AbstractInterface* iface, bool testClock) = 0; + virtual bool canConnectFrom(AbstractInterface* iface, bool testClock) = 0; // others void resetOutputPattern() { outputPattern = NULL; } diff --git a/DelayInputModifier.cpp b/DelayInputModifier.cpp index db89107..242547c 100644 --- a/DelayInputModifier.cpp +++ b/DelayInputModifier.cpp @@ -34,11 +34,12 @@ QString DelayInputModifier::toVHDL(int context, int flags) throw(Exception) { dm2.setNum(delayLength-2); dm3.setNum(delayLength-3); QString ret=""; - QString clkName = "clk"; - QString resetName = "reset"; + int idClock = toIface->getClockDomain(); + QString clkName = "ext_clk_"+QString::number(idClock); + QString resetName = "ext_reset_"+QString::number(idClock); if (toIface->getOwner()->getParent()->isTopGroupBlock()) { - clkName = "from_clkrstgen_clk"; - resetName ="from_clkrstgen_reset"; + clkName = "from_clkrstgen_"+QString::number(idClock)+"_clk"; + resetName ="from_clkrstgen_"+QString::number(idClock)+"_reset"; } if (context == Architecture) { diff --git a/Dispatcher.cpp b/Dispatcher.cpp index 266160b..574243e 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -100,7 +100,16 @@ void Dispatcher::setSceneCounter(Context context, int value) { } bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) { - + static QString fctName = "Dispatcher::createConnection()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + bool testClock = false; + if (context == Design) { + testClock = true; + } + ConnectedInterface* ref1 = iface1->refInter; ConnectedInterface* ref2 = iface2->refInter; // connect both interface @@ -108,30 +117,33 @@ bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, Interf bool ok1 = false; bool ok2 = false; + cout << "trying to create a connection between " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); + cout << " and " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); + // test the ref1->ref2 connection - if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) { + if ((ref1->canConnectTo(ref2,testClock)) && (ref2->canConnectFrom(ref1,testClock))) { ref1->connectTo(ref2); ok1 = true; } // if the first one did not work, test ref2->ref1 - if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) { + if ((ok1 == false) && (ref2->canConnectTo(ref1,testClock)) && (ref1->canConnectFrom(ref2,testClock))) { ref2->connectTo(ref1); ok2 = true; } if ((ok1 == true) || (ok2 == true)) { if (ok1) { - cout << "trying to create a connection from " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); + cout << " ... done with " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); cout << " to " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible); } else { - cout << "trying to create a connection from " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); + cout << "... done with " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); cout << " to " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); iface2->getOwner()->getScene()->createConnectionItem(iface2,iface1, visible); } - cout << " ... done." << endl; + cout << endl; unselectAllItems(context); params->unsaveModif = true; @@ -200,6 +212,12 @@ void Dispatcher::generateVHDL(Context context) throw(Exception) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + QDir baseDir(params->projectPath); QDir srcDir(params->projectPath+"/src"); @@ -304,6 +322,12 @@ void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + if (item->getRefBlock()->isFunctionalBlock()) { FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); @@ -321,6 +345,12 @@ void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupWidget* win = item->getScene()->getGroupWidget(); @@ -360,6 +390,12 @@ void Dispatcher::renameGroupBlock(Context context, GroupItem *item){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupWidget* win = item->getScene()->getGroupWidget(); @@ -406,6 +442,12 @@ void Dispatcher::renameStimuliItem(Context context, StimuliItem *item){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupWidget* win = item->getScene()->getGroupWidget(); @@ -446,6 +488,11 @@ void Dispatcher::renameInterface(Context context, InterfaceItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } GroupWidget* win = item->getOwner()->getScene()->getGroupWidget(); @@ -490,6 +537,12 @@ void Dispatcher::showPatterns(Context context, InterfaceItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + QString msg = ""; if (item->refInter->getDirection() == AbstractInterface::Input) { msg = "Input pattern of iface "; @@ -534,6 +587,12 @@ void Dispatcher::showModifier(Context context, InterfaceItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + QString msg = ""; ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface()); AbstractInputModifier* mod = assoIface->getInputModifier(); @@ -551,10 +610,16 @@ void Dispatcher::showModifier(Context context, InterfaceItem *item) { } void Dispatcher::removeModifier(Context context, InterfaceItem *item) { - static QString fctName = "Dispatcher::showModifier()"; + static QString fctName = "Dispatcher::removeModifier()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface()); assoIface->clearInputModifier(); @@ -566,6 +631,12 @@ void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){ #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupScene *scene = item->getScene(); AbstractBlock* block = item->getRefBlock(); @@ -589,6 +660,12 @@ void Dispatcher::duplicateStimuliItem(Context context, StimuliItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupScene *scene = item->getScene(); AbstractBlock* block = item->getRefBlock(); @@ -612,6 +689,12 @@ void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + AbstractInterface *refI = item->refInter; if (! refI->isFunctionalInterface()) return; @@ -1106,8 +1189,11 @@ void Dispatcher::removeBoxItem(Context context, BoxItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - - if (context != Design) return; + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } /* a BoxItem (group of func) can be removed only if none of its interfaces is connected to a group interface that is itself @@ -1182,6 +1268,11 @@ void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *ite #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getInterfaces()) { foreach(ConnectionItem* conn, ifaceItem->connections) { @@ -1195,6 +1286,11 @@ void Dispatcher::removeStimuliItem(Context context, StimuliItem *item) { #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getFromInterfaceItem(); InterfaceItem* toIfaceItem = connItem->getToInterfaceItem(); @@ -1291,6 +1393,16 @@ void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) { void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clkName, int idGen) throw(Exception) { + static QString fctName = "Dispatcher::connectBoxItemClock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(clkName); GroupItem* parentGroup = item->getScene()->getGroupItem(); @@ -1324,6 +1436,17 @@ void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clk } void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rstName, int idGen) throw(Exception) { + + static QString fctName = "Dispatcher::connectBoxItemReset()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(rstName); GroupItem* parentGroup = item->getScene()->getGroupItem(); @@ -1357,6 +1480,17 @@ void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rst } void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QString clkName, int idGen) throw(Exception) { + + static QString fctName = "Dispatcher::connectStimuliItemClock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(clkName); BoxItem* clkrstItem = NULL; @@ -1381,6 +1515,16 @@ void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QSt } void Dispatcher::connectStimuliItemReset(Context context, StimuliItem *item, QString rstName, int idGen) throw(Exception) { + static QString fctName = "Dispatcher::connectStimuliItemReset()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(rstName); BoxItem* clkrstItem = NULL; @@ -1412,6 +1556,17 @@ void Dispatcher::showBlocksLibrary(){ } void Dispatcher::showProperties(Context context, InterfaceItem *inter) { + + static QString fctName = "Dispatcher::showProperties()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <exec(); } @@ -1424,6 +1579,16 @@ void Dispatcher::showProperties(Context context, InterfaceItem *inter) { */ void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){ + static QString fctName = "Dispatcher::connectInterToGroup()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <refInter; cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl; @@ -1445,7 +1610,12 @@ void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){ parentItem->addInterfaceItem(groupIfaceItem,true); // creating the connection, in graph and with an item - createConnection(context, item, groupIfaceItem); + /* NOTE: + Since the group interface is for now unconnected, it is impossible to determine + its clock domain. Thus, the connection must be created without testing the clock domain + consistency. For that, we cheat by changing the context to Load because it implies no clock test. + */ + createConnection(Load, item, groupIfaceItem); // if groupItem is not topGroup, must also add a new interface to the parent BlockItem BoxItem* parent2Item = parentItem->getParentItem(); @@ -1465,6 +1635,11 @@ void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <computeAdmittanceDelays(); // get the block item that is associated to block diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp index 89250ec..98e5e87 100644 --- a/FunctionalBlock.cpp +++ b/FunctionalBlock.cpp @@ -1422,12 +1422,19 @@ void FunctionalBlock::generateComments(QTextStream& out, QDomElement &elt, QStri QDomElement eltModif = nodeModif.toElement(); } out << "-- Description : " << endl; - out << reference->getDescription() << endl; + QStringList lines = reference->getDescription().split("\n"); + foreach(QString line, lines) { + out << "-- " << line << endl; + } out << "--" << endl; QDomElement eltNote = eltLog.nextSiblingElement("notes"); QDomElement note = eltNote.firstChildElement(); QString noteTxt = note.text(); - out << "-- Notes :\n"<getWidthString(); direction = reference->getDirection(); purpose = reference->getPurpose(); - connectedFrom = NULL; + connectedFrom = NULL; + clkIfaceName = reference->getClockIfaceString(); + clkIfaceType = reference->getClockIfaceType(); } bool FunctionalInterface::isFunctionalInterface() { @@ -82,7 +84,12 @@ AbstractInterface *FunctionalInterface::clone() { return inter; } -bool FunctionalInterface::canConnectTo(AbstractInterface *iface) { +bool FunctionalInterface::canConnectTo(AbstractInterface *iface, bool testClock) { + static QString fctName = "FunctionalInterface::canConnectTo()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NOTE : necessary conditions : @@ -99,14 +106,19 @@ bool FunctionalInterface::canConnectTo(AbstractInterface *iface) { 2.2 - both are inout 3 - this is owned by a source block and iface is owned by the top group + + if testClock is true, must test if both ifaces are in the same clock domain. Note that a group interface + has always special case : clk/reset from clkrstgen can connect to stimuli clk/reset */ + bool ok = false; + if (direction == Input) return false; if (iface->isReferenceInterface()) return false; ConnectedInterface* connIface = AI_TO_CON(iface); if (connIface->getConnectedFrom() != NULL) return false; - // special case + + // special case, NB: never tests clocks if ((getOwner()->getName().startsWith("clkrstgen")) && (iface->getOwner()->isStimuliBlock())) { if ((direction == Output) && (iface->getDirection() == Input)) { if ((purpose == AbstractInterface::Clock) && (iface->getPurpose() == AbstractInterface::Clock)) return true; @@ -117,23 +129,48 @@ bool FunctionalInterface::canConnectTo(AbstractInterface *iface) { // first case: interface of blocks within the same group if (getOwner()->getParent() == iface->getOwner()->getParent()) { - if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + + + if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } // second case: iface = interface of the group that contains owner of this else if (getOwner()->getParent() == iface->getOwner()) { - if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if ((getOwner()->isStimuliBlock()) && (iface->getOwner()->isTopGroupBlock())) { - if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; + if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; } + if (ok) { + if (testClock) { + int dom1 = -1,dom2 = -2; + try { + dom1 = getClockDomain(); + dom2 = iface->getClockDomain(); + } + catch(Exception e) { + cerr << qPrintable(fctName) << " - " << qPrintable(e.getMessage()) << endl; + return false; + } + if (dom1 != dom2) { + cout << "cannot connect interface that are in different clock domains" << endl; + return false; + } + } + return true; + } return false; } -bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) { +bool FunctionalInterface::canConnectFrom(AbstractInterface *iface, bool testClock) { + + static QString fctName = "FunctionalInterface::canConnectFrom()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif /* NOTE : necessary conditions : @@ -151,11 +188,13 @@ bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) { special case : clk/reset of stimuli can connect from clk/reset of clkrstgen */ + bool ok = false; + if (direction == Output) return false; if (iface->isReferenceInterface()) return false; if (connectedFrom != NULL) return false; - // special case + // special case, NB: never tests clock if ((iface->getOwner()->getName().startsWith("clkrstgen")) && (getOwner()->isStimuliBlock())) { if ((direction == Input) && (iface->getDirection() == Output)) { if ((purpose == AbstractInterface::Clock) && (iface->getPurpose() == AbstractInterface::Clock)) return true; @@ -163,14 +202,32 @@ bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) { } } - if (getOwner()->getParent() == iface->getOwner()->getParent()) { - - if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if (getOwner()->getParent() == iface->getOwner()->getParent()) { + if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if (getOwner()->getParent() == iface->getOwner()) { - if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; + } + + if (ok) { + if (testClock) { + int dom1 = -1,dom2 = -2; + try { + dom1 = getClockDomain(); + dom2 = iface->getClockDomain(); + } + catch(Exception e) { + cerr << qPrintable(e.getMessage()) << endl; + return false; + } + if (dom1 != dom2) { + cout << "cannot connect interfaces that are in different clock domains" << endl; + return false; + } + } + return true; } return false; @@ -195,21 +252,27 @@ int FunctionalInterface::getClockDomain() throw(Exception) { if (connFrom == NULL) throw(Exception(IFACE_INVALID_CLKFREQ,this)); if (connFrom->getOwner()->isFunctionalBlock()) { - QString name = connFrom->getOwner()->getName(); - cout << "conn from clkrstgen: searching for clkdomain in " << qPrintable(name) << endl; - name.remove(0,10); - bool ok; - idClock = name.toInt(&ok); + QString domName = connFrom->getOwner()->getName(); + domName.remove(0,10); + cout << "conn from clkrstgen: searching for clkdomain in " << qPrintable(domName) << endl; + + bool ok = true; + idClock = domName.toInt(&ok); + cout << "id clock = " << idClock << endl; if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this)); } - else { - QString name = connFrom->getName(); - cout << "conn from group: searching for clkdomain in " << qPrintable(name) << endl; - name.remove(0,8); - bool ok; - idClock = name.toInt(&ok); + else if (connFrom->getOwner()->isGroupBlock()) { + QString domName = connFrom->getName(); + domName.remove(0,8); + cout << "conn from group: searching for clkdomain in " << qPrintable(domName) << endl; + + bool ok = true; + idClock = domName.toInt(&ok); if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this)); } + else { + cout << "abnormal case while searching for clkdomain" << endl; + } } return idClock; diff --git a/FunctionalInterface.h b/FunctionalInterface.h index 3c70703..6d0731a 100644 --- a/FunctionalInterface.h +++ b/FunctionalInterface.h @@ -45,8 +45,8 @@ public : // testers bool isFunctionalInterface(); - bool canConnectTo(AbstractInterface* iface); - bool canConnectFrom(AbstractInterface* iface); + bool canConnectTo(AbstractInterface* iface, bool testClock); + bool canConnectFrom(AbstractInterface* iface, bool testClock); // others diff --git a/Graph.cpp b/Graph.cpp index d0c11cc..2b43baa 100644 --- a/Graph.cpp +++ b/Graph.cpp @@ -3,6 +3,8 @@ #include "ReferenceBlock.h" #include "FunctionalBlock.h" #include "SpecialBlock.h" +#include "BlockParameter.h" +#include "ConnectedInterface.h" Graph::Graph() { topGroup = NULL; @@ -275,6 +277,7 @@ void Graph::generateTestbench(const QString &projectName, const QString &benchFi out << "use IEEE.numeric_std.all;" << endl; out << "entity " << projectName << "_tb is" << endl; out << "end entity " << projectName << "_tb;" << endl << endl; + out << "architecture " << projectName << "_tb_1 of " << projectName << "_tb is" << endl << endl; out << " component clock_gen" << endl; @@ -287,7 +290,238 @@ void Graph::generateTestbench(const QString &projectName, const QString &benchFi out << " end component;" << endl << endl; topGroup->generateComponent(out,false); + foreach(FunctionalBlock* block, stimulis) { + block->generateComponent(out,false); + } + + out << " ----------------------------" << endl; + out << " -- SIGNALS" << endl; + out << " ----------------------------" << endl << endl; + + out << " -- signals to reset stimulis" << endl; + foreach(FunctionalBlock* block, stimulis) { + out << " signal reset_" << block->getName() << " : std_logic;" << endl; + } + out << endl; + + out << " -- signals for external clocks/reset" << endl; + for(int i=0;igetName() << endl; + QList listInputs = block->getInputs(); + foreach(AbstractInterface* iface, listInputs) { + if (iface->getPurpose() == AbstractInterface::Data) { + out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; + } + } + } + catch(Exception e) { + throw(e); + } + try { + out << " -- signals from output ports of " << block->getName() << endl; + QList listOutputs = block->getOutputs(); + foreach(AbstractInterface* iface, listOutputs) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; + } + } + } + catch(Exception e) { + throw(e); + } + out << endl; + } + out << endl; + + // signals out of top group + try { + out << " -- signals from output ports of " << topGroup->getName() << endl; + QList listOutputs = topGroup->getOutputs(); + foreach(AbstractInterface* iface, listOutputs) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; + } + } + } + catch(Exception e) { + throw(e); + } + out << endl; + + // signals out of top group + try { + out << " -- signals from inout ports of " << topGroup->getName() << endl; + QList listBidirs = topGroup->getBidirs(); + foreach(AbstractInterface* iface, listBidirs) { + if (iface->getPurpose() == AbstractInterface::Data) { + out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; + } + } + } + catch(Exception e) { + throw(e); + } + out << endl; + + out << "begin" << endl; + // for now assign all external resets to fixed 0 because of clkrstgen in top group + for(int i=0;i " << halfPer << " ns" << endl; + out << " )" << endl; + out << " port map (" << endl; + out << " phase => ext_clk_" << i << endl; + out << " );" << endl << endl; + } + // generate instances of stimulis + foreach(FunctionalBlock* block, stimulis) { + try { + out << " " << block->getName() << "_1 : " << block->getName() << endl; + + QList listGenerics = block->getGenericParameters(); + QList listInputs = block->getInputs(); + QList listOutputs = block->getOutputs(); + + if (!listGenerics.isEmpty()) { + out << " generic map (" << endl; + int i; + for(i=0;itoVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl; + } + out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl; + out << " )" << endl; + } + + out << " port map (" << endl; + QString portMap = ""; + + for(int i=0;igetPurpose() == AbstractInterface::Data) || (connIface->getPurpose() == AbstractInterface::Control)) { + portMap += " " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n"; + } + else if (connIface->getPurpose() == AbstractInterface::Clock) { + // get the "fake" clkrstgen from which it is connected + ConnectedInterface* fromIface = connIface->getConnectedFrom(); + QString clkrstName = fromIface->getOwner()->getName(); + clkrstName.remove(0,10); + portMap += " " + connIface->getName() + " => ext_clk_" + clkrstName + ",\n"; + } + else if (connIface->getPurpose() == AbstractInterface::Reset) { + portMap += " " + connIface->getName() + " => reset_" + block->getName()+",\n"; + } + } + for(int i=0;igetName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n"; + } + portMap.chop(2); + out << portMap << endl; + + + out << " );" << endl; + } + catch(Exception e) { + throw(e); + } + out << endl; + } + out << endl; + // generate instance of top group + try { + out << " " << topGroup->getName() << "_1 : " << topGroup->getName() << endl; + + QList listGenerics = topGroup->getGenericParameters(); + QList listInputs = topGroup->getInputs(); + QList listOutputs = topGroup->getOutputs(); + QList listBidirs = topGroup->getBidirs(); + + if (!listGenerics.isEmpty()) { + out << " generic map (" << endl; + int i; + for(i=0;itoVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl; + } + out << " " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl; + out << " )" << endl; + } + + out << " port map (" << endl; + QString portMap = ""; + + for(int i=0;igetPurpose() == AbstractInterface::Data) || (connIface->getPurpose() == AbstractInterface::Control)) { + ConnectedInterface* fromIface = connIface->getConnectedFrom(); + portMap += " " + connIface->getName() + " => " + fromIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n"; + } + else if ( (connIface->getPurpose() == AbstractInterface::Clock) || (connIface->getPurpose() == AbstractInterface::Reset)) { + portMap += " " + connIface->getName() + " => " + connIface->getName() + ",\n"; + } + } + for(int i=0;igetName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n"; + } + for(int i=0;igetName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n"; + } + portMap.chop(2); + out << portMap << endl; + + + out << " );" << endl; + } + catch(Exception e) { + throw(e); + } + out << endl; + + // generate process for stimulis + foreach(FunctionalBlock* block, stimulis) { + // getting the start input + AbstractInterface* startIface = block->getIfaceFromName("start"); + if (startIface == NULL) continue; + double per = 1000.0/startIface->getClockFrequency(); + QString startName = block->getName()+"_start"; + out << " from_" << block->getName() << " : process" << endl; + out << " variable pclk : time := " << per << " ns;" << endl; + out << " begin" << endl; + out << " reset_" << block->getName() << " <= '0';" << endl; + out << " " << startName << " <= '0';" << endl; + out << " wait for 2*pclk;" << endl; + out << " reset_" << block->getName() << " <= '1';" << endl; + out << " wait for 1*pclk;" << endl; + out << " reset_" << block->getName() << " <= '0';" << endl; + out << " wait for 5*pclk;" << endl; + out << " " << startName << " <= '1';" << endl; + out << " wait for pclk;" << endl; + out << " " << startName << " <= '0';" << endl << endl; + out << " wait for 100000 us;" << endl; + out << " end process from_" << block->getName() << ";" << endl; + } + out << "end architecture " << projectName << "_tb_1;" << endl; vhdlBench.close(); } diff --git a/GroupBlock.cpp b/GroupBlock.cpp index d3ff0ed..d78a28e 100644 --- a/GroupBlock.cpp +++ b/GroupBlock.cpp @@ -7,6 +7,7 @@ #include #include "Parameters.h" #include "DelayInputModifier.h" +#include "Graph.h" int GroupBlock::counter = 1; @@ -484,16 +485,18 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( out << " -- SIGNALS" << endl; out << " ----------------------------" << endl << endl; - // signals to synchronize inputs - out << " -- signals to synchronize inputs" << endl; - foreach(AbstractInterface* iface, getInputs()) { - if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { - QString name = iface->toVHDL(AbstractInterface::Signal,0); - name.replace(" : ","_sync : "); - out << " signal " << name<< endl; + // if this is top group, signals to synchronize inputs + if (topGroup) { + out << " -- signals to synchronize inputs" << endl; + foreach(AbstractInterface* iface, getInputs()) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + QString name = iface->toVHDL(AbstractInterface::Signal,0); + name.replace(" : ","_sync : "); + out << " signal " << name<< endl; + } } + out << endl; } - out << endl; // "normal" signals foreach(AbstractBlock* block, blocks) { @@ -504,7 +507,7 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; } - else if (block->getName() == "clkrstgen") { + else if (block->getName().startsWith("clkrstgen")) { if ((iface->getPurpose() == AbstractInterface::Clock)||(iface->getPurpose() == AbstractInterface::Reset)) { out << " signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl; } @@ -668,36 +671,54 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw( } if (topGroup) { - // generate input sync process + // generate input sync process for each clock domain out << " -- process to synchronize inputs of top group" << endl; - out << "sync_inputs : process(from_clkrstgen_clk,from_clkrstgen_reset)" << endl; - out << " begin" << endl; - out << " if from_clkrstgen_reset = '1' then" << endl; - foreach(AbstractInterface* iface, getInputs()) { - if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { - if (iface->getWidth() == 0) { - out << " " << name << "_" << iface->getName() << "_sync <= '0';" << endl; - } - else { - out << " " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl; + for(int i=0;igetClocks().size();i++) { + // check if there are some inputs that must be sync with clock domain i + bool mustSync = false; + foreach(AbstractInterface* iface, getInputs()) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + if (iface->getClockDomain() == i) { + mustSync = true; + break; + } } } - } - out << " elsif rising_edge(from_clkrstgen_clk) then" << endl; - foreach(AbstractInterface* iface, getInputs()) { - if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { - if (iface->getWidth() == 0) { - out << " " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl; + if (mustSync) { + out << "sync_inputs_" << i << " : process(from_clkrstgen_" << i << "_clk,from_clkrstgen_" << i << "_reset)" << endl; + out << " begin" << endl; + out << " if from_clkrstgen_" << i << "_reset = '1' then" << endl; + foreach(AbstractInterface* iface, getInputs()) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + if (iface->getClockDomain() == i) { + if (iface->getWidth() == 0) { + out << " " << name << "_" << iface->getName() << "_sync <= '0';" << endl; + } + else { + out << " " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl; + } + } + } } - else { - out << " " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl; + out << " elsif rising_edge(from_clkrstgen_" << i << "_clk) then" << endl; + foreach(AbstractInterface* iface, getInputs()) { + if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) { + if (iface->getClockDomain() == i) { + if (iface->getWidth() == 0) { + out << " " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl; + } + else { + out << " " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl; + } + } + } } + out << " end if;" << endl; + out << " end process sync_inputs_" << i << ";" << endl; + + out << endl; } } - out << " end if;" << endl; - out << " end process sync_inputs;" << endl; - - out << endl; } out << "end architecture rtl;" << endl; diff --git a/GroupInterface.cpp b/GroupInterface.cpp index bfeb1ff..db80b91 100644 --- a/GroupInterface.cpp +++ b/GroupInterface.cpp @@ -10,6 +10,7 @@ GroupInterface::GroupInterface(AbstractBlock* _owner, const QString& _name, int if ((purpose == Clock) || (purpose == Reset)) { type = Boolean; } + clkIfaceType = InheritedName; } bool GroupInterface::isGroupInterface() { @@ -44,7 +45,7 @@ int GroupInterface::getWidth() { return w; } -bool GroupInterface::canConnectTo(AbstractInterface *iface) { +bool GroupInterface::canConnectTo(AbstractInterface *iface, bool testClock) { /* NOTE : necessary conditions : @@ -62,32 +63,53 @@ bool GroupInterface::canConnectTo(AbstractInterface *iface) { 2.1 - this is an output, iface is an output of the group 2.2 - both are inout - + NB: testClock is useless since a group interface has always a clkIfaceType inherited. + Thus, it is always possible */ + bool ok = false; + if (iface->isReferenceInterface()) return false; ConnectedInterface* connIface = AI_TO_CON(iface); if (connIface->getConnectedFrom() != NULL) return false; if (this->getOwner() == iface->getOwner()->getParent()) { - if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) { - if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if (this->getOwner()->getParent() == iface->getOwner()) { - if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } + if (ok) { + if (testClock) { + int dom1 = -1,dom2 = -2; + try { + dom1 = getClockDomain(); + dom2 = iface->getClockDomain(); + } + catch(Exception e) { + cerr << qPrintable(e.getMessage()) << endl; + return false; + } + if (dom1 != dom2) { + cout << "cannot connect interface that are in different clock domains" << endl; + return false; + } + } + return true; + } return false; } -bool GroupInterface::canConnectFrom(AbstractInterface *iface) { +bool GroupInterface::canConnectFrom(AbstractInterface *iface, bool testClock) { /* NOTE : necessary conditions : @@ -106,24 +128,45 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) { 2.2 - both are inout 4 - this is owned by top group and iface is an output of a source block */ + bool ok = false; + if (iface->isReferenceInterface()) return false; if (getConnectedFrom() != NULL) return false; if (this->getOwner() == iface->getOwner()->getParent()) { - if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) { - if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if (this->getOwner()->getParent() == iface->getOwner()) { - if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true; - if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true; + if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true; + if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true; } else if ((getOwner()->isTopGroupBlock()) && (iface->getOwner()->isStimuliBlock())) { - if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true; + if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true; + } + + if (ok) { + if (testClock) { + int dom1 = -1,dom2 = -2; + try { + dom1 = getClockDomain(); + dom2 = iface->getClockDomain(); + } + catch(Exception e) { + cerr << qPrintable(e.getMessage()) << endl; + return false; + } + if (dom1 != dom2) { + cout << "cannot connect interface that are in different clock domains" << endl; + return false; + } + } + return true; } return false; @@ -131,29 +174,60 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) { int GroupInterface::getClockDomain() throw(Exception) { + /* For clk/rst interfaces, the clock domain can be deduced + from the interface name. + Otherwise, we can search backward/forward for a functional + interface. Since a group interface cannot exist if it is not + connected to and/or from a functional interface (either directly + or through a sequence of subgroups) there is at least such a functional + interface. + */ int idClock = -1; - - GroupInterface* iface = NULL; - if (clkIfaceType == ClockName) { - iface = AI_TO_GRP(getClockIface()); - } - else if ((direction == Input) && (purpose == Clock)) { - iface = this; - } - - if ( iface != NULL) { - - QString name = iface->getName(); - name.remove(0,8); + if ((purpose == Clock) || (purpose == Reset)) { + QString domName = name; + domName.remove(0,8); bool ok; - idClock = name.toInt(&ok); + idClock = domName.toInt(&ok); if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this)); - + } + else { + // start by searching backward + ConnectedInterface* connFrom = connectedFrom; + while ((connFrom != NULL) && (connFrom->isGroupInterface())) { + connFrom = connFrom->getConnectedFrom(); + } + if (connFrom != NULL) { + idClock = connFrom->getClockDomain(); + } + //searching forward + else { + QList lstIfaces = getForwardFunctionalInterfaces(this); + if (lstIfaces.isEmpty()) throw(Exception(IFACE_INVALID_CLKFREQ,this)); + foreach(ConnectedInterface* iface, lstIfaces) { + // test if all ifaces are in the same clock domain + if (idClock == -1) { + idClock = iface->getClockDomain(); + } + else if (idClock != iface->getClockDomain()) throw(Exception(IFACE_INVALID_CLKFREQ,this)); + } + } } return idClock; } +QList GroupInterface::getForwardFunctionalInterfaces(GroupInterface* groupIface) { + QList lstIfaces; + foreach(ConnectedInterface* iface, groupIface->getConnectedTo()) { + if (iface->isFunctionalInterface()) { + lstIfaces.append(iface); + } + else if (iface->isGroupInterface()) { + lstIfaces.append(getForwardFunctionalInterfaces(AI_TO_GRP(iface))); + } + } + return lstIfaces; +} void GroupInterface::connectionsValidation(QStack *interfacetoValidate, QList *validatedInterfaces) throw(Exception) { cout << "group interface connection validation" << endl; diff --git a/GroupInterface.h b/GroupInterface.h index 35f0916..6bedd67 100644 --- a/GroupInterface.h +++ b/GroupInterface.h @@ -10,6 +10,7 @@ #include "Exception.h" class Exception; + using namespace std; using namespace Qt; @@ -43,11 +44,13 @@ public : // testers bool isGroupInterface(); - bool canConnectTo(AbstractInterface* iface); - bool canConnectFrom(AbstractInterface* iface); + bool canConnectTo(AbstractInterface* iface, bool testClock); + bool canConnectFrom(AbstractInterface* iface, bool testClock); // others AbstractInterface *clone(); + QList getForwardFunctionalInterfaces(GroupInterface* groupIface); + void connectionsValidation(QStack *interfacetoValidate, QList *validatedInterfaces) throw(Exception); }; diff --git a/InterfacePropertiesDialog.cpp b/InterfacePropertiesDialog.cpp index cc0a3ad..fb76c71 100644 --- a/InterfacePropertiesDialog.cpp +++ b/InterfacePropertiesDialog.cpp @@ -32,6 +32,8 @@ InterfacePropertiesDialog::InterfacePropertiesDialog(InterfaceItem *_inter, QWid layProp->addWidget(new QLabel(inter->refInter->getPurposeString()), 5, 1); layProp->addWidget(new QLabel("Type :"), 6, 0); layProp->addWidget(new QLabel(inter->refInter->getTypeString()), 6, 1); + layProp->addWidget(new QLabel("related to clock :"), 7, 0); + layProp->addWidget(new QLabel(inter->refInter->getClockIfaceString()), 7, 1); QHBoxLayout* layBottom = new QHBoxLayout; layBottom->addStretch(); diff --git a/MainWindow.cpp b/MainWindow.cpp index 99f13bb..6f4716a 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -311,9 +311,14 @@ void MainWindow::save(QString projectFile) { params->save(projectFile); } -void MainWindow::slotLoadProject(){ +void MainWindow::slotLoadProject(QString fileName){ - params->projectFile = QFileDialog::getOpenFileName(0, "select a project file", "save/",tr("sauvegardes (*.xml)")); + if (fileName == "") { + params->projectFile = QFileDialog::getOpenFileName(0, "select a project file", "save/",tr("sauvegardes (*.xml)")); + } + else { + params->projectFile = fileName; + } if(! params->projectFile.isEmpty()){ GroupWidget* topGroup = dispatcher->loadProject(params->projectFile); diff --git a/MainWindow.h b/MainWindow.h index 96fab67..613b3d1 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -121,10 +121,10 @@ 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 + void slotLoadProject(QString fileName = ""); private slots: - void slotNewProject(); - void slotLoadProject(); + void slotNewProject(); void slotSaveProject(); void slotSaveAsProject(); bool slotCloseProject(); diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp index 553955b..56a34db 100644 --- a/ReferenceBlock.cpp +++ b/ReferenceBlock.cpp @@ -80,7 +80,7 @@ void ReferenceBlock::load(QDomElement &elt) throw(Exception) { // create interfaces that correspond to a wishbone parameter, if any. try { - createInterfaceForParameters(); + createInterfaceForWishbone(); } catch(int err) { throw(err); @@ -220,7 +220,7 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { int purpose; QString multStr; int mult; - AbstractInterface* inter; + ReferenceInterface* iface; if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED)); @@ -236,9 +236,12 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { purposeStr = eltInput.attribute("purpose","none"); if (purposeStr == "clock") { nameStr = eltInput.attribute("name","none"); - inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1); - inputs.append(inter); - clocks.append(inter); + iface = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1); + if (! iface->checkSetClockIface(nameStr)) { + throw (Exception(BLOCKFILE_CORRUPTED)); + } + inputs.append(iface); + clocks.append(iface); } } cout << "number of clocks: " << clocks.size() << endl; @@ -270,15 +273,19 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { multStr = eltInput.attribute("multiplicity","none"); mult = ReferenceInterface::translateMultiplicity(multStr); - inter = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult); + iface = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult); if (clockStr == "none") { - // no clock given, take the first one (hope that there is a single one !) + if (clocks.size() > 1) { + // if several clocks, the associated one MUST be given + throw (Exception(BLOCKFILE_CORRUPTED)); + } + // no clock given, take the single one clockStr = clocks.at(0)->getName(); } - if (! inter->setClockIface(clockStr)) { + if (! iface->checkSetClockIface(clockStr)) { throw (Exception(BLOCKFILE_CORRUPTED)); } - inputs.append(inter); + inputs.append(iface); } } // getting each control @@ -289,13 +296,17 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { nameStr = eltInput.attribute("iface","none"); AbstractInterface* dataIface = getIfaceFromName(nameStr); if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED)); - nameStr = dataIface->getName()+"_enb"; - inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1); - if (!inter->setAssociatedIface(dataIface)) { + QString nameEnbStr = dataIface->getName()+"_enb"; + iface = new ReferenceInterface(this,nameEnbStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1); + if (!iface->setAssociatedIface(dataIface)) { throw (Exception(BLOCKFILE_CORRUPTED)); } - cout << "created a control input named " << qPrintable(inter->getName()) << endl; - inputs.append(inter); + clockStr = dataIface->getClockIfaceString(); + if (! iface->checkSetClockIface(clockStr)) { + throw (Exception(BLOCKFILE_CORRUPTED)); + } + cout << "created a control input named " << qPrintable(iface->getName()) << endl; + inputs.append(iface); } QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs"); QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output"); @@ -323,15 +334,20 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { multStr = eltOutput.attribute("multiplicity","none"); mult = ReferenceInterface::translateMultiplicity(multStr); - inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult); + iface = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult); if (clockStr == "none") { - // no clock given, take the first one (hope that there is a single one !) + if (clocks.size() > 1) { + // if several clocks, the associated one MUST be given + throw (Exception(BLOCKFILE_CORRUPTED)); + } + // no clock given, take the single one clockStr = clocks.at(0)->getName(); } - if (! inter->setClockIface(clockStr)) { + if (! iface->checkSetClockIface(clockStr)) { throw (Exception(BLOCKFILE_CORRUPTED)); } - outputs.append(inter); + + outputs.append(iface); } // getting each control QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control"); @@ -342,12 +358,16 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { AbstractInterface* dataIface = getIfaceFromName(nameStr); if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED)); nameStr = dataIface->getName()+"_enb"; - inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1); - if (!inter->setAssociatedIface(dataIface)) { + iface = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1); + if (!iface->setAssociatedIface(dataIface)) { throw (Exception(BLOCKFILE_CORRUPTED)); } - cout << "created a control output named " << qPrintable(inter->getName()) << endl; - outputs.append(inter); + clockStr = dataIface->getClockIfaceString(); + if (! iface->checkSetClockIface(clockStr)) { + throw (Exception(BLOCKFILE_CORRUPTED)); + } + cout << "created a control output named " << qPrintable(iface->getName()) << endl; + outputs.append(iface); } QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs"); @@ -375,19 +395,24 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) { multStr = eltBidir.attribute("multiplicity","none"); mult = ReferenceInterface::translateMultiplicity(multStr); - inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult); + iface = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult); if (clockStr == "none") { - // no clock given, take the first one (hope that there is a single one !) + if (clocks.size() > 1) { + // if several clocks, the associated one MUST be given + throw (Exception(BLOCKFILE_CORRUPTED)); + } + // no clock given, take the single one clockStr = clocks.at(0)->getName(); } - if (! inter->setClockIface(clockStr)) { + if (! iface->checkSetClockIface(clockStr)) { throw (Exception(BLOCKFILE_CORRUPTED)); } - bidirs.append(inter); + + bidirs.append(iface); } } -void ReferenceBlock::createInterfaceForParameters() throw(Exception){ +void ReferenceBlock::createInterfaceForWishbone() throw(Exception){ ReferenceInterface* iface = NULL; foreach(BlockParameter* param, params) { @@ -484,7 +509,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) { toWrite << iface->getClockIfaceString(); } } - // secondly, write other ifaces + // thirdly, write other ifaces for(int i=0; igetPurpose() != AbstractInterface::Control) && (iface->getPurpose() != AbstractInterface::Clock)) { @@ -624,13 +649,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { QString clk; in >> clkType; in >> clk; - if (clkType == AbstractInterface::ParameterName) { - clk = "$"+clk; - } - if (! iface->setClockIface(clk)) { - cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl; - } - + iface->setClockIfaceName(clk); + iface->setClockIfaceType(clkType); b.inputs.append(iface); if (iface->getPurpose() == AbstractInterface::Data) { QString ctlRefName = iface->getName()+"_enb"; @@ -664,12 +684,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { QString clk; in >> clkType; in >> clk; - if (clkType == AbstractInterface::ParameterName) { - clk = "$"+clk; - } - if (! iface->setClockIface(clk)) { - cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl; - } + iface->setClockIfaceName(clk); + iface->setClockIfaceType(clkType); b.outputs.append(iface); if (iface->getPurpose() == AbstractInterface::Data) { QString ctlRefName = iface->getName()+"_enb"; @@ -703,12 +719,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) { QString clk; in >> clkType; in >> clk; - if (clkType == AbstractInterface::ParameterName) { - clk = "$"+clk; - } - if (! iface->setClockIface(clk)) { - cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl; - } + iface->setClockIfaceName(clk); + iface->setClockIfaceType(clkType); b.bidirs.append(iface); } diff --git a/ReferenceBlock.h b/ReferenceBlock.h index 2aca879..63dca3c 100644 --- a/ReferenceBlock.h +++ b/ReferenceBlock.h @@ -61,7 +61,7 @@ private: void loadInformations(QDomElement &elt) throw(Exception); void loadParameters(QDomElement &elt) throw(Exception); void loadInterfaces(QDomElement &elt) throw(Exception); - void createInterfaceForParameters() throw(Exception); + void createInterfaceForWishbone() throw(Exception); friend QDataStream &operator<<(QDataStream &out, const ReferenceBlock &b); friend QDataStream &operator>>(QDataStream &in, ReferenceBlock &b); diff --git a/ReferenceInterface.cpp b/ReferenceInterface.cpp index fdebeaa..ae5613b 100644 --- a/ReferenceInterface.cpp +++ b/ReferenceInterface.cpp @@ -1,5 +1,6 @@ #include "ReferenceInterface.h" #include "AbstractBlock.h" +#include "BlockParameter.h" ReferenceInterface::ReferenceInterface(AbstractBlock* _owner) throw(Exception) : AbstractInterface(_owner) { if (_owner->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE)); @@ -76,3 +77,92 @@ int ReferenceInterface::getClockDomain() throw(Exception) { throw(Exception(IFACE_INVALID_TYPE,this)); } + +/* NOTE on clock associated to each interface: + + Each interface must be associated to a clock so that blast can determine + if there are no problems with clocks domains. This clock must correspond to + the name of a clock interface owned by the same block or to a user parameter + for which the value indicate the clock frequency. This latter case is used only + for input interfaces of blocks that will be directly linked to the outside of top group + (NB: directly only means that there are no others functional blocks between the + mentionnned block and the outside, but it can be within subgroups) and with these interfaces + that receives a data signal synchronized on an outside clock that is not provided to the design. + For example, on the APF27 board, there is a link between imx and spartan 3 and signals are at 133MHz. + But there is no clock provided to the FPGA. + + Reference blocks are created with: + - input clocks are associated to themselves. + - output clocks are associated to one of the clock. + - reset are associated to one of the clock (since they are generated + by clkrstgen, they are really synchronized with a clock) + - all other signals are associated to one of the clock or to a parameter + The name of the associated clock is given in the xml description file. If not + indicated it is by default the name of the input clock. In case of there are + several input clocks, the xml is incoherent if other signal do not indicate the name of + the associated clock. + + Functional block are created by cloning a reference thus they follow the same rules as + reference blocks. + + A group is created with interfaces that have an inherited clock name thus, setting a name + is meaningless and an iterative process must be used to retrieve the clock domain from + the interface that is connected from the group interface (cf. GroupBlock::getClockDomain()) + + The following method checks if these rules are applied correctly. + +*/ +bool ReferenceInterface::checkSetClockIface(QString _name) { + + /* 3 cases : + - this is a clock input: name must be the same as the iface name + - this is an output clock or reset: name must be an existing clock name. + - other cases: name must ba a parameter name or an exisiting clock name + + NB: if it's a parameter it must be prepend with a $. + */ + if ((purpose == Clock) && (direction == Input)) { + if (_name == name) { + clkIfaceName = _name; + clkIfaceType = ClockName; + return true; + } + } + else if ((purpose == Reset) || ((purpose == Clock) && (direction == Output))) { + QList clocks = owner->getInterfaces(Input, Clock); + foreach(AbstractInterface* iface, clocks) { + if (iface->getName() == _name) { + clkIfaceName = _name; + clkIfaceType = ClockName; + return true; + } + } + } + else { + if (_name.at(0) == '$') { + _name.remove(0,1); + QList params = owner->getUserParameters(); + foreach(BlockParameter* p, params) { + if (p->getName() == _name) { + clkIfaceName = _name; + clkIfaceType = ParameterName; + return true; + } + } + } + else { + QList clocks = owner->getInterfaces(Input, Clock); + foreach(AbstractInterface* iface, clocks) { + if (iface->getName() == _name) { + clkIfaceName = _name; + clkIfaceType = ClockName; + return true; + } + } + } + } + clkIfaceName = ""; + clkIfaceType = NoName; + return false; +} + diff --git a/ReferenceInterface.h b/ReferenceInterface.h index cf54f4a..68c0179 100644 --- a/ReferenceInterface.h +++ b/ReferenceInterface.h @@ -31,6 +31,7 @@ public : bool isReferenceInterface(); // others + bool checkSetClockIface(QString _name); static int translatePurpose(const QString& txt); static int translateMultiplicity(const QString& txt); diff --git a/blast.cpp b/blast.cpp index 35dd592..763a8d2 100644 --- a/blast.cpp +++ b/blast.cpp @@ -12,6 +12,9 @@ int main(int argc, char *argv[]) { MainWindow w; w.show(); + if (argc == 2) { + w.slotLoadProject(argv[1]); + } return a.exec(); } diff --git a/blast.creator.user b/blast.creator.user index 34b8287..fb924e9 100644 --- a/blast.creator.user +++ b/blast.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/blastconfig.xml b/blastconfig.xml index 26ec97a..05d683a 100644 --- a/blastconfig.xml +++ b/blastconfig.xml @@ -2,12 +2,12 @@ - + - + diff --git a/lib/implementations/clkdomain_convert_1024x8_impl.xml b/lib/implementations/clkdomain_convert_1024x8_impl.xml index 6046ebe..aa35dfe 100644 --- a/lib/implementations/clkdomain_convert_1024x8_impl.xml +++ b/lib/implementations/clkdomain_convert_1024x8_impl.xml @@ -60,8 +60,6 @@ if empty = '0' then end if; end if; end process read_fifo; - -end architecture clkdomain_convert_1024x8_1; diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf index 3fc15fe..6802074 100644 Binary files a/lib/implementations/impls.bmf and b/lib/implementations/impls.bmf differ diff --git a/lib/implementations/read_csv_impl.xml b/lib/implementations/read_csv_impl.xml index aa5e00f..389bbb3 100644 --- a/lib/implementations/read_csv_impl.xml +++ b/lib/implementations/read_csv_impl.xml @@ -62,7 +62,7 @@ new_line <= '0'; item_count := 0; line_count := 0; last_line := '0'; -out_enb <= '0'; +@{out_val_enb} <= '0'; dly_item_count := 0; dly_line_count := 0; item_count_enb := '0'; @@ -70,7 +70,7 @@ line_count_enb := '0'; elsif rising_edge(@{clk}) then -out_enb <= '0'; +@{out_val_enb} <= '0'; if do_read = '1' then @@ -101,7 +101,7 @@ end if; else read(l, in_val); out_s <= to_unsigned(in_val, item_width); -out_enb <= '1'; +@{out_val_enb} <= '1'; item_count := item_count + 1; if (item_count < item_per_line) then read(l, comma); @@ -121,7 +121,7 @@ end if; end if; end if; -elsif start_read = '1' then +elsif @{start} = '1' then -- reading the first line readline(in_data, l); line_count := line_count + 1; @@ -132,8 +132,6 @@ do_read <= '1'; end if; end process read_data; - -end architecture read_csv_a; diff --git a/lib/references/clkdomain_convert_1024x8.xml b/lib/references/clkdomain_convert_1024x8.xml index b6e19c4..59f84ed 100644 --- a/lib/references/clkdomain_convert_1024x8.xml +++ b/lib/references/clkdomain_convert_1024x8.xml @@ -7,15 +7,12 @@ This IP allows to pass 8 bits values from a clock domain to another. It uses a FIFO of 1024 entries. - - - - + - + diff --git a/lib/references/generator-cst.xml b/lib/references/generator-cst.xml index 2ddf876..112add7 100644 --- a/lib/references/generator-cst.xml +++ b/lib/references/generator-cst.xml @@ -4,7 +4,7 @@ generator-cst - + generates V consecutives constant values, followed by Z idle cycles @@ -21,6 +21,7 @@ + diff --git a/lib/references/generator-img.xml b/lib/references/generator-img.xml index dfc18eb..0c350f6 100644 --- a/lib/references/generator-img.xml +++ b/lib/references/generator-img.xml @@ -4,7 +4,7 @@ generator-img - + generates a RGB image, reading if from a csv file @@ -21,6 +21,7 @@ + diff --git a/lib/references/read_csv.xml b/lib/references/read_csv.xml index c8fd7f1..d738413 100644 --- a/lib/references/read_csv.xml +++ b/lib/references/read_csv.xml @@ -2,7 +2,7 @@ read_csv - + read a csv file @@ -20,6 +20,8 @@ + + diff --git a/lib/references/references.bmf b/lib/references/references.bmf index ffc13f1..bdb7010 100644 Binary files a/lib/references/references.bmf and b/lib/references/references.bmf differ