]> AND Private Git Repository - blast.git/commitdiff
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
started adding delta comput
authorstephane Domas <stephane.domas@univ-fcomte.fr>
Fri, 12 May 2017 14:46:45 +0000 (16:46 +0200)
committerstephane Domas <stephane.domas@univ-fcomte.fr>
Fri, 12 May 2017 14:46:45 +0000 (16:46 +0200)
25 files changed:
AbstractBlock.cpp
AbstractBlock.h
AbstractInterface.h
ArithmeticEvaluator.cpp
BlockImplementation.cpp
BlockImplementation.h
BlockParameter.cpp
BlockParameter.h
BlockParameterUser.cpp
BlockParameterUser.h
BoxItem.cpp
FunctionalBlock.cpp
FunctionalBlock.h
Graph.cpp
Graph.h
GroupBlock.cpp
GroupBlock.h
Parameters.cpp
ReferenceBlock.cpp
ReferenceBlock.h
blast.creator.user
implementation.xsd
lib/implementations/average-Nx3_impl.xml
lib/implementations/impls.bmf
lib/references/references.bmf

index c71b2e0c508e46719659e2e15ba8982a69cdaf66..66c8f37a13c208a0646f7043fd120590351af2b5 100644 (file)
@@ -51,11 +51,12 @@ bool AbstractBlock::isTopGroupBlock() {
 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
@@ -126,42 +127,58 @@ void AbstractBlock::defineBlockParam(BlockParameter *param)
   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
index c8aa0235dd989cb85708eedaad66bbf5a5b9fd70..88e4cb91076e0323eeb141263282e629206f5bad 100644 (file)
@@ -5,6 +5,7 @@
 \r
 #include <QtCore>\r
 \r
+#include "AbstractInterface.h"\r
 class AbstractInterface;\r
 class BlockParameter;\r
 \r
@@ -43,6 +44,7 @@ public:
   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
@@ -62,15 +64,16 @@ public:
   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
@@ -90,6 +93,7 @@ protected:
   // 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
index e26f5c5975ae424c761ba29824dee3ce01f1bcc4..ac47ca9f4ba774445e0b349b7c220622c8bfe693 100644 (file)
@@ -24,9 +24,9 @@ class AbstractInterface {
 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);  
index 60db08e1265cfda852725112b896c5a6a7526a7b..dd8081ea03eccca986313810960688c032ea9af9 100644 (file)
@@ -165,15 +165,19 @@ double ArithmeticEvaluator::evaluate() throw(int) {
  */
 
 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 {
index af06ef357c778739ec58a2d6f16d6b856863318d..e6b61caa640d6eb10dff9035d11a0998f103d843 100644 (file)
@@ -5,10 +5,13 @@
 #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
@@ -16,32 +19,69 @@ BlockImplementation::BlockImplementation(const QString& _xmlFile) {
 \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
@@ -527,7 +567,12 @@ QDataStream& operator<<(QDataStream &out, const BlockImplementation &impl) {
   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
@@ -544,6 +589,11 @@ QDataStream& operator>>(QDataStream &in, BlockImplementation &impl) {
   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
index 852cc63df288780db229e4d4914d36895cd62313..4866e859559c5c8dabe55e705f2cad47d5ebdc6c 100644 (file)
@@ -28,9 +28,16 @@ public:
   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
@@ -40,7 +47,8 @@ public:
 \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
@@ -53,6 +61,10 @@ private:
   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
index f8dfcd736018b7b2674d046d537589c946a430d0..620714895e23fbd10cbf68755ac0e9a4607a1696 100644 (file)
@@ -22,6 +22,37 @@ QVariant BlockParameter::getValue() {
   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
index adc8c5d15192f39ae72568a9356d96a4083e8fe8..e8068d4b6b70d68b9c95dae94db0dae7bbf24eff 100644 (file)
@@ -44,6 +44,10 @@ public :
   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
index d0d870fd9108ca16f3344cfa76af7500a2248477..b6665fa7d2bebddb04d79feeaf87068436d533b1 100644 (file)
@@ -4,7 +4,7 @@ BlockParameterUser::BlockParameterUser() : BlockParameter() {
   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
@@ -30,7 +30,7 @@ bool BlockParameterUser::isDefaultValue() {
 }\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
index 3da12a3d59256be8492aae92a230a14105d5e290..59589811e462de810c0bf666bd774ff2c9cf407f 100644 (file)
@@ -29,7 +29,7 @@ class BlockParameterUser : public BlockParameter {
 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
index 92f89b81995d25989a3d6d02be35ec90082f39d8..568e946458a69a7b9604901f114479be7d0780fd 100644 (file)
@@ -624,7 +624,11 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
   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);
   }    
 }
index 93e83775a979f3eb3bd9af7dc66c306a555ab092..5731794da37211ed6872f1b7c88ca3c703e74a79 100644 (file)
@@ -18,7 +18,14 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference
   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
@@ -106,7 +113,69 @@ QString FunctionalBlock::getReferenceHashMd5() {
     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
@@ -137,11 +206,24 @@ void FunctionalBlock::computeOutputPattern(int nbExec) {
       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
@@ -237,6 +319,7 @@ void FunctionalBlock::computeOutputPattern(int nbExec) {
     }\r
     delete [] outputPattern;\r
   }\r
+  return true;\r
 }\r
 \r
 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
index 9852eb7b33e25c89f94733316066b6e39cc3f1c1..f8989906f59a839561e09780eefcf7466441bd02 100644 (file)
@@ -11,6 +11,9 @@ class ReferenceBlock;
 class GroupBlock;\r
 #include "Exception.h"\r
 class Exception;\r
+class BlockImplementation;\r
+class ArithmeticEvaluator;\r
+    \r
 \r
 \r
 using namespace std;\r
@@ -29,6 +32,7 @@ public:
   inline ReferenceBlock* getReference() { return reference; }\r
 \r
   // setters\r
+  inline void setImplementation(BlockImplementation* impl) { implementation = impl; }\r
 \r
   // testers\r
   bool isFunctionalBlock();\r
@@ -43,6 +47,11 @@ public:
   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
@@ -50,7 +59,7 @@ public:
   \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
@@ -71,8 +80,10 @@ private:
   char** productionPattern;\r
   int nbProducingPorts;\r
   int lengthPP;\r
+  ArithmeticEvaluator* evaluator;\r
   \r
   ReferenceBlock* reference;\r
+  BlockImplementation* implementation;\r
 \r
 };\r
 \r
index a4dd676142370731391ddb74333e256195e6ea90..d3fd276d6dc9e6191a5485863cb4e0aae6f0ac9d 100644 (file)
--- a/Graph.cpp
+++ b/Graph.cpp
@@ -107,3 +107,37 @@ bool Graph::removeSourceBlock(FunctionalBlock *block) {
   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);
+    }
+  }
+}
diff --git a/Graph.h b/Graph.h
index 7be35c27523d24f91d2a0534c0f8397620150731..b2b807833e852a892d4384cf75abca5fda9c53dd 100644 (file)
--- a/Graph.h
+++ b/Graph.h
@@ -43,7 +43,15 @@ public:
   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:  
index 716cea644ec148c3ced17883a9d132c2e7785199..a8a06e641a7156b93de9de6ae52fbbaafb47b78e 100644 (file)
@@ -1,6 +1,7 @@
 #include "GroupBlock.h"
 #include "BlockParameterGeneric.h"
 #include "AbstractInterface.h"
+#include "ConnectedInterface.h"
 #include "string.h"
 #include <sstream>
 
@@ -110,13 +111,65 @@ void GroupBlock::initInputPattern() {
   }  
 }
 
-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;
 }
index 0aeb0069a01e6b2a341dbbb993ce9ebe03570754..547159ef52199424ed410fb72de7275c9be3fad1 100644 (file)
@@ -52,7 +52,7 @@ private:
    * 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
index c12fead572453807169c5e905bab6592a6c2e07b..3cc8c14aa33cae92dba77a39939c80de0d9b8b43 100644 (file)
@@ -683,6 +683,12 @@ void Parameters::loadImplementationsFromXml() throw(Exception) {
       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
@@ -694,9 +700,12 @@ void Parameters::loadImplementationsFromXml() throw(Exception) {
       }\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
@@ -741,8 +750,11 @@ void Parameters::loadImplementationsFromLib() throw(Exception) {
     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
index ae7f0ce6ca80825a0301a7f34c97a6021054850b..12db4b4a9bc683b99cddea0c3ed0724e7d7e4ae2 100644 (file)
@@ -157,7 +157,7 @@ void ReferenceBlock::loadParameters(QDomElement &elt) throw(Exception) {
         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);
@@ -471,7 +471,7 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
     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);
@@ -567,6 +567,7 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
   return in;
 }
 
-void ReferenceBlock::computeOutputPattern(int nbExec) {
+bool ReferenceBlock::computeOutputPattern(int nbExec) {
   // does strictly nothing
+  return false;
 }
index 2e34984d09dbd8f4ee7be82d15056224e31fc5bd..b10c1429852d7762c2a795d3d49052ba4f9bad22 100644 (file)
@@ -68,7 +68,7 @@ public:
   
 private:
   // patterns
-  void computeOutputPattern(int nbExec = -1);
+  bool computeOutputPattern(int nbExec = -1);
 };
 
 #endif // __REFERENCEBLOCK_H__
index b9d826a447bd9eb01a78ac1bb4d9e6e998b50214..a4cb21ce96f379098962fea5345b2e060dff317d 100755 (executable)
@@ -1,10 +1,10 @@
 <?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">
index 0dff1f667a888854ef0caf142ddade2b61c9d9bb..c8385148e3ef1b53be83f50239a81884c519f98a 100644 (file)
            <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>
     
index 1ea7a7fa282790fced1128b42c1a5d77d216e878..de874d1dddec290d90d3740805943101b1fbeb0b 100644 (file)
@@ -28,8 +28,8 @@
     <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>
index 7fd7598fad1ca6067e30c3313a113855cddb779d..15dfac4ea57ccf0c25326ec2f4d067d82a1d427a 100644 (file)
Binary files a/lib/implementations/impls.bmf and b/lib/implementations/impls.bmf differ
index 7eefb86f5b9c126156af3b149b5029ce13bb34fd..60ea24991a6600f046e574563d7088b2a29e4a9e 100644 (file)
Binary files a/lib/references/references.bmf and b/lib/references/references.bmf differ