bool AbstractBlock::isSourceBlock() {\r
return false;\r
}\r
-\r
+/* NB: a generator is a block that has no data inputs\r
+ * and has at least one data output.\r
+ */\r
bool AbstractBlock::isGeneratorBlock() {\r
- foreach(AbstractInterface* iface, inputs) {\r
- if (iface->getPurpose() == AbstractInterface::Data) return false;\r
- }\r
+ if (getDataInputs().size() > 0) return false;\r
+ \r
return true;\r
}\r
\r
param->setValue(value); \r
}\r
\r
-QList<AbstractInterface *> AbstractBlock::getInterfaces() {\r
+QList<AbstractInterface *> AbstractBlock::getInterfaces(int direction, int purpose) {\r
QList<AbstractInterface *> list;\r
- list.append(inputs);\r
- list.append(outputs);\r
- list.append(bidirs);\r
+ bool selIn = false;\r
+ bool selOut = false;\r
+ bool selInOut = false;\r
+ \r
+ if (direction == AbstractInterface::AnyDirection) {\r
+ selIn = true;\r
+ selOut = true;\r
+ selInOut = true;\r
+ }\r
+ else if (direction == AbstractInterface::Input) {\r
+ selIn = true; \r
+ }\r
+ else if (direction == AbstractInterface::Output) {\r
+ selOut = true; \r
+ }\r
+ else if (direction == AbstractInterface::InOut) {\r
+ selInOut = true; \r
+ }\r
+ if (selIn) {\r
+ foreach(AbstractInterface* iface, inputs) {\r
+ if ((iface->getPurpose() == purpose) || (purpose == AbstractInterface::AnyPurpose)) list.append(iface); \r
+ }\r
+ }\r
+ if (selOut) {\r
+ foreach(AbstractInterface* iface, outputs) {\r
+ if ((iface->getPurpose() == purpose) || (purpose == AbstractInterface::AnyPurpose)) list.append(iface); \r
+ }\r
+ }\r
+ if (selInOut) {\r
+ foreach(AbstractInterface* iface, bidirs) {\r
+ if ((iface->getPurpose() == purpose) || (purpose == AbstractInterface::AnyPurpose)) list.append(iface); \r
+ }\r
+ }\r
return list;\r
}\r
\r
QList<AbstractInterface *> AbstractBlock::getDataInputs() {\r
- QList<AbstractInterface *> list;\r
- foreach(AbstractInterface* iface, inputs) {\r
- if (iface->getPurpose() == AbstractInterface::Data) {\r
- list.append(iface);\r
- }\r
- }\r
- return list;\r
+ return getInterfaces(AbstractInterface::Input, AbstractInterface::Data); \r
+}\r
+\r
+QList<AbstractInterface *> AbstractBlock::getDataOutputs() {\r
+ return getInterfaces(AbstractInterface::Output, AbstractInterface::Data); \r
}\r
\r
QList<AbstractInterface *> AbstractBlock::getControlInputs() {\r
- QList<AbstractInterface *> list;\r
- foreach(AbstractInterface* iface, inputs) {\r
- if (iface->getPurpose() == AbstractInterface::Control) {\r
- list.append(iface);\r
- }\r
- }\r
- return list;\r
+ return getInterfaces(AbstractInterface::Input, AbstractInterface::Control); \r
}\r
\r
QList<AbstractInterface *> AbstractBlock::getControlOutputs() {\r
- QList<AbstractInterface *> list;\r
- foreach(AbstractInterface* iface, outputs) {\r
- if (iface->getPurpose() == AbstractInterface::Control) {\r
- list.append(iface);\r
- }\r
- }\r
- return list;\r
+ return getInterfaces(AbstractInterface::Output, AbstractInterface::Control); \r
}\r
\r
AbstractInterface* AbstractBlock::getIfaceFromName(QString name) {\r
\r
#include <QtCore>\r
\r
+#include "AbstractInterface.h"\r
class AbstractInterface;\r
class BlockParameter;\r
\r
virtual void setParent(AbstractBlock* _parent);\r
inline void setProductionCounter(QList<int> pattern) { productionCounter = pattern; }\r
inline void setDelta(int _delta) { delta = _delta; }\r
+ inline void setPatternComputed(bool state) { patternComputed = state; }\r
\r
// testers\r
virtual bool isReferenceBlock();\r
void removeAllInterfaces();\r
void defineBlockParam(BlockParameter *param);\r
\r
- QList<AbstractInterface *> getInterfaces(); //! return all interfaces\r
+ QList<AbstractInterface *> getInterfaces(int direction = AbstractInterface::AnyDirection, int purpose = AbstractInterface::AnyPurpose);\r
QList<AbstractInterface *> getDataInputs(); //! return all inputs of type data\r
+ QList<AbstractInterface *> getDataOutputs(); //! return all inputs of type data\r
QList<AbstractInterface *> getControlInputs(); //! return all inputs of type control\r
QList<AbstractInterface *> getControlOutputs(); //! return all outputs of type control\r
AbstractInterface* getIfaceFromName(QString name);\r
BlockParameter* getParameterFromName(QString name);\r
\r
// patterns\r
- virtual void computeOutputPattern(int nbExec = -1) = 0;\r
+ virtual bool computeOutputPattern(int nbExec = -1) = 0;\r
\r
protected:\r
\r
// patterns\r
QList<int> productionCounter; //! only usefull for output interfaces\r
int delta;\r
+ bool patternComputed;\r
\r
// NB: only GroupBlock and FunctionalBlock have a real parent, except sources that have no parents\r
AbstractBlock* parent;\r
public :
enum IfaceWidthType { Expression = 1, Boolean, Natural, Inherited}; //! Inherited is only for Group interface
- enum IfacePurpose { Data = 1, Control, Clock, Reset, Wishbone };
- enum IfaceDirection { Input = 1, Output = 2, InOut = 3 };
- enum IfaceVHDLContext { Entity = 1, Component = 2, Architecture = 3 }; // NB : 3 is when creating an instance of the block that owns this iface
+ enum IfacePurpose { AnyPurpose = 0, Data = 1, Control, Clock, Reset, Wishbone };
+ enum IfaceDirection { AnyDirection = 0, Input = 1, Output = 2, InOut = 3 };
+ enum IfaceVHDLContext {AnyContext = 0, Entity = 1, Component = 2, Architecture = 3 }; // NB : 3 is when creating an instance of the block that owns this iface
enum IfaceVHDLFlags { NoComma = 1 };
static int getIntDirection(QString str);
*/
void ArithmeticEvaluator::convert(const QString& _expression) throw(int) {
- QString expr = _expression;
+
+ QString expr = _expression;
+ cout << "converting " << qPrintable(expr) << endl;
QString result="";
expr.remove(QChar(' '), Qt::CaseInsensitive);
+ cout << "converting " << qPrintable(expr) << endl;
foreach(QString func, fctMarkers) {
+ cout << "for " << qPrintable(func) << endl;
QString rep = QString("\x1b%1").arg(fctMarkers.indexOf(QRegExp(func)));
expr.replace(QRegExp(func),rep);
}
- //cout << "packed expr: " << qPrintable(expr) << endl;
+ cout << "packed expr: " << qPrintable(expr) << endl;
int offset = 0;
try {
#include "ReferenceInterface.h"\r
#include "FunctionalInterface.h"\r
#include "BlockParameter.h"\r
+#include <QHashIterator>\r
\r
\r
BlockImplementation::BlockImplementation(const QString& _xmlFile) {\r
- xmlFile = _xmlFile; \r
+ xmlFile = _xmlFile;\r
+ productionCounter = "";\r
+ delta = "";\r
\r
evaluator = new ArithmeticEvaluator;\r
evaluator->setVariableMarkers("@$");\r
\r
BlockImplementation::BlockImplementation(const QString& _xmlFile, const QString &_referenceXml, const QString &_referenceMd5) {\r
xmlFile = _xmlFile; \r
+ productionCounter = "";\r
+ delta = "";\r
referenceXml = _referenceXml;\r
referenceMd5 = _referenceMd5;\r
}\r
\r
-void BlockImplementation::assignPatterns(FunctionalBlock *_block) throw(Exception) {\r
+void BlockImplementation::loadPatterns(QDomElement& root) throw(Exception) {\r
+ \r
+ QDomNodeList patternNode = root.elementsByTagName("patterns");\r
\r
- block = _block;\r
-\r
- QFile implFile(xmlFile);\r
-\r
- // reading in into QDomDocument\r
- QDomDocument document("implFile");\r
-\r
- if (!implFile.open(QIODevice::ReadOnly)) {\r
- throw(Exception(IMPLFILE_NOACCESS));\r
- }\r
- if (!document.setContent(&implFile)) {\r
- implFile.close();\r
- throw(Exception(IMPLFILE_NOACCESS));\r
+ if (patternNode.isEmpty()) {\r
+ cout << "impl has no patterns" << endl;\r
+ return;\r
}\r
- implFile.close();\r
- QDomElement impl = document.documentElement();\r
- QDomNodeList patternNode = impl.elementsByTagName("patterns");\r
- if (patternNode.isEmpty()) return;\r
+ \r
QDomElement patternElt = patternNode.at(0).toElement();\r
\r
+ QDomElement eltDelta = patternElt.firstChildElement("delta");\r
+ delta = eltDelta.attribute("value","none");\r
+ \r
+ QDomElement eltCons = eltDelta.nextSiblingElement("consumption");\r
+ \r
+ QDomNodeList listNodeInput = eltCons.elementsByTagName("input");\r
+ for(int i=0; i<listNodeInput.size(); i++) {\r
+ QDomNode node = listNodeInput.at(i); \r
+ QDomElement elt = node.toElement(); \r
+ QString nameStr = elt.attribute("name","none");\r
+ if (nameStr == "none") throw(Exception(IMPLFILE_CORRUPTED));\r
+ QString patternStr = elt.attribute("pattern","none"); \r
+ consumptionPattern.insert(nameStr,patternStr);\r
+ }\r
+ \r
+ QDomElement eltProd = eltCons.nextSiblingElement("production");\r
+ productionCounter = eltProd.attribute("counter","none");\r
+ QDomNodeList listNodeOutput = eltCons.elementsByTagName("output");\r
+ for(int i=0; i<listNodeOutput.size(); i++) {\r
+ QDomNode node = listNodeOutput.at(i); \r
+ QDomElement elt = node.toElement(); \r
+ QString nameStr = elt.attribute("name","none");\r
+ if (nameStr == "none") throw(Exception(IMPLFILE_CORRUPTED));\r
+ QString patternStr = elt.attribute("pattern","none"); \r
+ productionPattern.insert(nameStr,patternStr); \r
+ }\r
+ cout << "impls patterns read correctly" << endl;\r
+}\r
+\r
+bool BlockImplementation::checkPatterns() {\r
+ if (reference == NULL) return false;\r
+ \r
+ AbstractInterface* iface; \r
+ QHashIterator<QString,QString> iterI(consumptionPattern);\r
+ while (iterI.hasNext()) {\r
+ iterI.next();\r
+ iface = reference->getIfaceFromName(iterI.key());\r
+ if (iface == NULL) return false;\r
+ }\r
+ QHashIterator<QString,QString> iterO(productionPattern);\r
+ while (iterO.hasNext()) {\r
+ iterO.next();\r
+ iface = reference->getIfaceFromName(iterO.key());\r
+ if (iface == NULL) return false;\r
+ } \r
+ return true; \r
}\r
\r
void BlockImplementation::generateVHDL(FunctionalBlock* _block, const QString &path) throw(Exception) {\r
toWrite << impl.xmlFile;\r
toWrite << impl.referenceXml;\r
toWrite << impl.referenceMd5;\r
-\r
+ // saving patterns\r
+ toWrite << impl.delta;\r
+ toWrite << impl.consumptionPattern;\r
+ toWrite << impl.productionPattern;\r
+ toWrite << impl.productionCounter;\r
+ \r
out << blockData;\r
\r
return out;\r
in >> impl.xmlFile;\r
in >> impl.referenceXml;\r
in >> impl.referenceMd5;\r
+ // loading patterns\r
+ in >> impl.delta;\r
+ in >> impl.consumptionPattern;\r
+ in >> impl.productionPattern;\r
+ in >> impl.productionCounter;\r
\r
return in;\r
}\r
BlockImplementation(const QString& _xmlFile);\r
BlockImplementation(const QString& _xmlFile, const QString& _referenceXml, const QString& _referenceMd5);\r
\r
+ // getters \r
inline QString getXmlFile() { return xmlFile; }\r
inline QString getReferenceXml() { return referenceXml; }\r
inline QString getReferenceMd5() { return referenceMd5; }\r
+ inline QString getDelta() { return delta; }\r
+ inline QHash<QString,QString> getConsumptionPattern() { return consumptionPattern; }\r
+ inline QHash<QString,QString> getProductionPattern() { return productionPattern; }\r
+ inline QString getProductionCounter() { return productionCounter; }\r
+ // setters\r
+ \r
QString eval(QString line, QTextStream& out);\r
QString evalComplex(QString line, int num);\r
QString evalString(QString s);\r
\r
inline void setReference(ReferenceBlock* _reference) { reference = _reference; }\r
\r
- void assignPatterns(FunctionalBlock* _block) throw(Exception); // called during output pattern computation\r
+ void loadPatterns(QDomElement &root) throw(Exception);\r
+ bool checkPatterns();\r
void generateVHDL(FunctionalBlock* _block, const QString& path) throw(Exception); // main entry to generate the VHDL code\r
\r
\r
ArithmeticEvaluator* evaluator;\r
ReferenceBlock* reference;\r
FunctionalBlock* block; // the current functional block for which this implementation is used.\r
+ QString delta;\r
+ QHash<QString,QString> consumptionPattern; // key = reference interface name, value = pattern expression\r
+ QHash<QString,QString> productionPattern; // key = reference interface name, value = pattern expression\r
+ QString productionCounter;\r
\r
void generateComments(QDomElement &elt,QString coreFile, QTextStream& out) throw(Exception); // generates comments from <comments> element\r
void generateLibraries(QDomElement &elt, QTextStream& out) throw(Exception); // generates libraries from <libraries> element\r
return defaultValue;\r
}\r
\r
+bool BlockParameter::getBooleanValue(bool* ok) {\r
+ if (type == Boolean) {\r
+ *ok = true;\r
+ return getValue().toBool();\r
+ }\r
+ *ok = false;\r
+ return false;\r
+}\r
+\r
+int BlockParameter::getIntValue(bool* ok) {\r
+ if ((type == Natural) || (type == Positive) || (type == Integer)) {\r
+ *ok = true;\r
+ return getValue().toInt();\r
+ }\r
+ *ok = false;\r
+ return 0;\r
+}\r
+\r
+double BlockParameter::getDoubleValue(bool* ok) {\r
+ if ((type == Real) || (type == Natural) || (type == Positive) || (type == Integer)) {\r
+ *ok = true;\r
+ return getValue().toDouble();\r
+ }\r
+ *ok = false;\r
+ return 0.0;\r
+}\r
+\r
+QString BlockParameter::getStringValue() {\r
+ return getValue().toString();\r
+}\r
+\r
bool BlockParameter::isUserParameter() {\r
return false;\r
\r
inline int getType() { return type; }\r
QString getTypeString();\r
virtual QVariant getValue(); // may be overriden\r
+ int getIntValue(bool* ok);\r
+ double getDoubleValue(bool* ok);\r
+ bool getBooleanValue(bool* ok); \r
+ QString getStringValue();\r
virtual QString getContext() = 0;\r
\r
// setters\r
userValue = defaultValue;\r
}\r
\r
-BlockParameterUser::BlockParameterUser(AbstractBlock* _owner, const QString &_name, const QString &_value) : BlockParameter(_owner, _name, "string", _value) {\r
+BlockParameterUser::BlockParameterUser(AbstractBlock* _owner, const QString &_name, const QString &_type, const QString &_value) : BlockParameter(_owner, _name, _type, _value) {\r
userValue = defaultValue;\r
}\r
\r
}\r
\r
BlockParameter* BlockParameterUser::clone() {\r
- BlockParameter* block = new BlockParameterUser(owner,name,defaultValue.toString());\r
+ BlockParameter* block = new BlockParameterUser(owner,name,getTypeString(), defaultValue.toString());\r
return block;\r
}\r
\r
public :\r
\r
BlockParameterUser();\r
- BlockParameterUser(AbstractBlock* _owner, const QString& _name, const QString& _value);\r
+ BlockParameterUser(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _value);\r
\r
// getters\r
QVariant getValue();\r
else if(selectedAction == showWishboneIface) {
dispatcher->showWishboneIface(this);
}
- else if(selectedAction == showParameters){
+ else if(selectedAction == showParameters) {
+ if (refBlock->isFunctionalBlock()) {
+ FunctionalBlock* fun = AB_TO_FUN(refBlock);
+ fun->createDelta();
+ }
new ParametersWindow(refBlock, params, NULL);
}
}
nbConsumingPorts = 0;\r
productionPattern = NULL;\r
lengthPP = 0;\r
- nbProducingPorts = 0; \r
+ nbProducingPorts = 0;\r
+ if (reference->getImplementations().isEmpty()) {\r
+ implementation = NULL;\r
+ cout << "block has no implementation" << endl;\r
+ }\r
+ else {\r
+ implementation = reference->getImplementations().at(0);\r
+ }\r
}\r
\r
\r
return ((ReferenceBlock *)reference)->getHashMd5();\r
}\r
\r
-void FunctionalBlock::computeOutputPattern(int nbExec) {\r
+bool FunctionalBlock::createPatterns() {\r
+ evaluator = new ArithmeticEvaluator();\r
+ bool ok = true;\r
+ ok = ok & createDelta();\r
+ if (ok) ok = ok & createConsumptionPattern();\r
+ if (ok) ok = ok & createProductionCounter();\r
+ if (ok) ok = ok & createProductionPattern();\r
+ delete evaluator;\r
+ return ok;\r
+}\r
+\r
+bool FunctionalBlock::createDelta() {\r
+ QString delta = implementation->getDelta();\r
+ cout << "delta for " << qPrintable(name) << " = " << qPrintable(delta) << endl;\r
+ \r
+ // look for parameter names\r
+ QHash<QString,double> vars;\r
+ QRegularExpression re("[$][a-zA-Z0-9_]+");\r
+ QRegularExpressionMatchIterator matcher = re.globalMatch(delta);\r
+ while(matcher.hasNext()) {\r
+ QRegularExpressionMatch m = matcher.next();\r
+ QString var = m.captured(0);\r
+ cout << qPrintable(var) << endl;\r
+ vars.insert(var,0.0); \r
+ }\r
+ QHashIterator<QString,double> iterV(vars);\r
+ while (iterV.hasNext()) {\r
+ iterV.next();\r
+ QString var = iterV.key();\r
+ QString paramName = var.remove(0,1);\r
+ BlockParameter* param = reference->getParameterFromName(paramName);\r
+ cout << "param = " << qPrintable(param->getStringValue()) << endl;\r
+ if (param == NULL) {\r
+ cerr << "found an unknown parameter in delta"<< endl;\r
+ return false;\r
+ }\r
+ bool ok;\r
+ int val = param->getIntValue(&ok);\r
+ vars.insert(var,(double)val);\r
+ }\r
+ cout << "set expr " << endl;\r
+ evaluator->setExpression(delta);\r
+ cout << "set vars " << endl;\r
+ evaluator->setVariablesValue(vars);\r
+ double result = evaluator->evaluate();\r
+ cout << "delta = " << result << endl;\r
+ \r
+ return true;\r
+}\r
+\r
+bool FunctionalBlock::createConsumptionPattern() {\r
+ return true;\r
+}\r
+\r
+bool FunctionalBlock::createProductionPattern() {\r
+ return true;\r
+}\r
+\r
+bool FunctionalBlock::createProductionCounter() {\r
+ return true;\r
+}\r
+\r
+bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
\r
/* case 1: the block is a generator for which output pattern\r
must be computed for a nbExec following executions\r
else {\r
if (in.size() < minLen) minLen = in.size();\r
}\r
- inputPattern[idIface] = new char[in.size()];\r
- int i = 0;\r
- foreach(char c, in) inputPattern[idIface][i++] = c;\r
+ if (in.size() > 0) {\r
+ inputPattern[idIface] = new char[in.size()];\r
+ int i = 0;\r
+ foreach(char c, in) inputPattern[idIface][i++] = c;\r
+ }\r
+ else {\r
+ inputPattern[idIface] = NULL;\r
+ }\r
idIface += 1; \r
}\r
+ // if some patterns are not available, ens now, returning false\r
+ if (minLen == 0) {\r
+ for(int i=0;i<nbConsumingPorts; i++) {\r
+ if (inputPattern[i] != NULL) delete [] inputPattern[i];\r
+ }\r
+ delete [] inputPattern;\r
+ return false;\r
+ }\r
// initialize the output pattern \r
char** outputPattern = NULL;\r
outputPattern = new char*[nbProducingPorts];\r
}\r
delete [] outputPattern;\r
}\r
+ return true;\r
}\r
\r
bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
class GroupBlock;\r
#include "Exception.h"\r
class Exception;\r
+class BlockImplementation;\r
+class ArithmeticEvaluator;\r
+ \r
\r
\r
using namespace std;\r
inline ReferenceBlock* getReference() { return reference; }\r
\r
// setters\r
+ inline void setImplementation(BlockImplementation* impl) { implementation = impl; }\r
\r
// testers\r
bool isFunctionalBlock();\r
QString getReferenceHashMd5();\r
\r
// patterns\r
+ bool createPatterns();\r
+ bool createDelta();\r
+ bool createConsumptionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation\r
+ bool createProductionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation\r
+ bool createProductionCounter(); // initialize a QList<int> from counter defined in implementation\r
void initConsumptionPattern(); // initialize a char** from patterns defined for each interface\r
void initProductionPattern(); // initialize a char** from patterns defined for each interface\r
void clearConsumptionPattern();\r
\r
private: \r
// patterns\r
- void computeOutputPattern(int nbExec = -1);\r
+ bool computeOutputPattern(int nbExec = -1);\r
bool isValidDataGroup(char** pattern, int nbPorts, int clock);\r
/*!\r
* \brief combinePatterns\r
char** productionPattern;\r
int nbProducingPorts;\r
int lengthPP;\r
+ ArithmeticEvaluator* evaluator;\r
\r
ReferenceBlock* reference;\r
+ BlockImplementation* implementation;\r
\r
};\r
\r
sources.removeAll(block);
return true;
}
+
+bool Graph::createPatterns() {
+ bool ok = true;
+ foreach(AbstractBlock* block, sources) {
+ FunctionalBlock* funBlock = AB_TO_FUN(block);
+ ok = funBlock->createPatterns();
+ if (!ok) return false;
+ }
+
+ foreach(AbstractBlock* block, groups) {
+ GroupBlock* group = AB_TO_GRP(block);
+ foreach(AbstractBlock* inBlock, group->getBlocks()) {
+ if (inBlock->isFunctionalBlock()) {
+ FunctionalBlock* funBlock = AB_TO_FUN(inBlock);
+ ok = funBlock->createPatterns();
+ if (!ok) return false;
+ }
+ }
+ }
+ return true;
+}
+
+void Graph::resetPatternComputed() {
+ foreach(AbstractBlock* block, sources) {
+ block->setPatternComputed(false);
+ }
+ foreach(AbstractBlock* block, groups) {
+ GroupBlock* group = AB_TO_GRP(block);
+ group->setPatternComputed(false);
+ foreach(AbstractBlock* inBlock, group->getBlocks()) {
+ inBlock->setPatternComputed(false);
+ }
+ }
+}
bool removeSourceBlock(FunctionalBlock* block);
// others
- QList<AbstractInterface *> getOutsideInterfaces();
+ QList<AbstractInterface *> getOutsideInterfaces();
+ /*!
+ * \brief initPatterns
+ * initPatterns() crosses the graph and for each functional block, it computes
+ * the consumptionPattern, the productionPattern, the production counter and delta
+ * using the parameters fo the block.
+ */
+ bool createPatterns();
+ void resetPatternComputed();
private:
#include "GroupBlock.h"
#include "BlockParameterGeneric.h"
#include "AbstractInterface.h"
+#include "ConnectedInterface.h"
#include "string.h"
#include <sstream>
}
}
-void GroupBlock::computeOutputPattern(int nbExec) {
+bool GroupBlock::computeOutputPattern(int nbExec) {
+ bool canCompute = true;
// get the input pattern on each inputs
initInputPattern();
- // find blocks that are connected to that inputs
- foreach(AbstractInterface* iface, getControlOutputs()) {
- iface->setOutputPattern(iface->getConnectedFrom()->getOutputPattern());
+ // find blocks that are connected to that inputs and generators
+ QList<AbstractBlock*> 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
+ foreach(AbstractInterface* iface, block->getControlInputs()) {
+ ConnectedInterface* conn = (ConnectedInterface*)iface;
+ ConnectedInterface* groupIface = conn->getConnectionFromParentGroup();
+ if (groupIface != NULL) {
+ addIt = true;
+ break;
+ }
+ }
+ }
+ if (addIt) fifo.append(block);
+ }
+ while (!fifo.isEmpty()) {
+ AbstractBlock* block = fifo.takeFirst();
+ cout << "computing pattern for " << qPrintable(block->getName()) << endl;
+ canCompute = block->computeOutputPattern();
+ if (!canCompute) {
+ cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
+ break;
+ }
+ block->setPatternComputed(true);
+ // add other blocks connected from block to the fifo
+ 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());
+ }
+ else if (connTo->getOwner() != this) {
+ fifo.append(connTo->getOwner());
+ }
+ }
+ }
+ }
+
+ if (canCompute) {
+ foreach(AbstractInterface* iface, getControlOutputs()) {
+ iface->setOutputPattern(iface->getConnectedFrom()->getOutputPattern());
+ }
+ setPatternComputed(true);
}
+ return canCompute;
}
* found by taking the output pattern of the connectedFrom interface.
*/
void initInputPattern();
- void computeOutputPattern(int nbExec = -1);
+ bool computeOutputPattern(int nbExec = -1);
bool topGroup;
QList<AbstractBlock*> blocks; // contains instances of FunctionalBlock or GroupBlock that are children of this group
QString refXml = implRoot.attribute("ref_name","none");\r
QString refMd5 = implRoot.attribute("ref_md5","none");\r
BlockImplementation* impl = new BlockImplementation(fileName,refXml,refMd5);\r
+ try {\r
+ impl->loadPatterns(implRoot);\r
+ }\r
+ catch(int err) {\r
+ throw(err);\r
+ }\r
availableImplementations.append(impl);\r
\r
ReferenceBlock* ref = NULL;\r
}\r
if (ref == NULL) {\r
cout << "Cannot find a reference block for impl :" << qPrintable(fileName) << endl;\r
- }\r
- ref->addImplementation(impl);\r
- impl->setReference(ref);\r
+ } \r
+ else { \r
+ ref->addImplementation(impl);\r
+ impl->setReference(ref);\r
+ if (! impl->checkPatterns()) throw(Exception(IMPLFILE_CORRUPTED));\r
+ } \r
cout << "OK" << endl;\r
}\r
}\r
if (ref == NULL) {\r
cout << "Cannot find a reference block for impl :" << qPrintable(impl->getXmlFile()) << endl;\r
}\r
- ref->addImplementation(impl);\r
- impl->setReference(ref);\r
+ else { \r
+ ref->addImplementation(impl);\r
+ impl->setReference(ref);\r
+ if (! impl->checkPatterns()) throw(Exception(IMPLFILE_CORRUPTED));\r
+ }\r
}\r
libFile.close();\r
}\r
valueStr = "";
}
if (contextStr == "user") {
- param = new BlockParameterUser(this,nameStr,valueStr);
+ param = new BlockParameterUser(this,nameStr,typeStr,valueStr);
}
else if (contextStr == "generic") {
param = new BlockParameterGeneric(this,nameStr,typeStr,valueStr);
in >> valueStr;
if (contextStr == "user") {
- p = new BlockParameterUser(&b,nameStr,valueStr);
+ p = new BlockParameterUser(&b,nameStr,typeStr,valueStr);
}
else if (contextStr == "generic") {
p = new BlockParameterGeneric(&b,nameStr,typeStr,valueStr);
return in;
}
-void ReferenceBlock::computeOutputPattern(int nbExec) {
+bool ReferenceBlock::computeOutputPattern(int nbExec) {
// does strictly nothing
+ return false;
}
private:
// patterns
- void computeOutputPattern(int nbExec = -1);
+ bool computeOutputPattern(int nbExec = -1);
};
#endif // __REFERENCEBLOCK_H__
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 3.2.1, 2017-05-11T21:36:51. -->
+<!-- Written by QtCreator 3.2.1, 2017-05-12T16:46:10. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
- <value type="QByteArray">{c8006d66-d34f-42be-ad10-d0207752286d}</value>
+ <value type="QByteArray">{1d077e47-e3a1-47fd-8b12-4de650e39df5}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
- <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{2c9bf876-3476-44eb-8065-1f0844704dda}</value>
+ <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{451ee8a3-56ff-4aba-8a8e-3da882cc142e}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
- <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/sdomas/Projet/Blast/code/blast</value>
+ <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/localhome/sdomas/Projet/Blast/code/blast</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
<xs:sequence>
<xs:element ref="output" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
+ <xs:attribute ref="counter" />
</xs:complexType>
</xs:element>
<xs:complexType>
<xs:attribute ref="name" />
<xs:attribute ref="pattern" />
- <xs:attribute ref="counter" />
</xs:complexType>
</xs:element>
<consumption>
<input name="data_i" pattern="(1){$nb_data}" />
</consumption>
- <production>
- <output name="data_o" pattern="00{$nb_data}" counter="{2:$nb_data+2:1}"/>
+ <production counter="{2:$nb_data+2:1}">
+ <output name="data_o" pattern="00{$nb_data}" />
</production>
</patterns>
</block_impl>