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

Private GIT Repository
pattern comput done
[blast.git] / FunctionalBlock.cpp
index 5731794da37211ed6872f1b7c88ca3c703e74a79..0db21c42398801f2097a9cc7c506f6ffb1d51da4 100644 (file)
@@ -5,6 +5,7 @@
 #include "FunctionalInterface.h"\r
 #include "ReferenceInterface.h"\r
 #include "BlockParameter.h"\r
+#include "ArithmeticEvaluator.h"\r
 \r
 \r
 FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) :  AbstractBlock() {\r
@@ -114,82 +115,311 @@ QString FunctionalBlock::getReferenceHashMd5() {
 }\r
 \r
 bool FunctionalBlock::createPatterns() {\r
+  static QString fctName = "FunctionalBlock::createPatterns()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  cout << "create patterns for block " << qPrintable(name) << endl;\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 (! isGeneratorBlock()) {\r
+    if (ok) ok = ok & createConsumptionPattern();\r
+    if (ok) ok = ok & createProductionCounter();\r
+  }\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
+  static QString fctName = "FunctionalBlock::createDelta()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif \r
+  \r
+  QString deltaStr = implementation->getDelta();\r
+  cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << 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
+  bool ok = true;\r
+  double result = evaluateExpression(deltaStr, &ok);\r
+  if (!ok) return false;\r
+  \r
+  delta = result;\r
+  cout << "delta = " << delta << endl;\r
    \r
   return true;\r
 }\r
 \r
 bool FunctionalBlock::createConsumptionPattern() {\r
+  static QString fctName = "FunctionalBlock::createConsumptionPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  bool ok = true; \r
+  QHash<QString,QString> consPattern = implementation->getConsumptionPattern();  \r
+  \r
+  foreach(AbstractInterface* iface, getControlInputs()) {       \r
+    FunctionalInterface* connIface = AI_TO_FUN(iface);\r
+    QString refName = connIface->getReference()->getName();    \r
+    if (! consPattern.contains(refName)) {\r
+      cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;\r
+      return false;\r
+    }\r
+    QList<char> pattern = expandPattern(consPattern.value(refName),&ok);    \r
+    \r
+    if (!ok) return false;\r
+    connIface->setConsumptionPattern(pattern);\r
+    cout << qPrintable(refName) << " consumption pattern = ";\r
+    foreach(char c, pattern) {\r
+      cout << (int)c << " ";\r
+    }\r
+    cout << endl;\r
+    \r
+  }        \r
   return true;\r
 }\r
 \r
-bool FunctionalBlock::createProductionPattern() {\r
+bool FunctionalBlock::createProductionPattern() {  \r
+  static QString fctName = "FunctionalBlock::createProductionPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  bool ok = true; \r
+  QHash<QString,QString> prodPattern = implementation->getProductionPattern();  \r
+  \r
+  foreach(AbstractInterface* iface, getControlOutputs()) {    \r
+    FunctionalInterface* connIface = AI_TO_FUN(iface);\r
+    QString refName = connIface->getReference()->getName();    \r
+    if (! prodPattern.contains(refName)) {\r
+      cerr << "no production pattern for reference interface " << qPrintable(refName) << endl;\r
+      return false;\r
+    }\r
+    QList<char> pattern = expandPattern(prodPattern.value(refName),&ok);\r
+    if (!ok) return false;\r
+    connIface->setProductionPattern(pattern);\r
+    cout << qPrintable(refName) << " production pattern = ";\r
+    foreach(char c, pattern) {\r
+      cout << (int)c << " ";\r
+    }\r
+    cout << endl;\r
+    \r
+  }    \r
   return true;\r
 }\r
 \r
 bool FunctionalBlock::createProductionCounter() {\r
+  static QString fctName = "FunctionalBlock::createProductionCounter()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  QStringList counterParts = implementation->getProductionCounter().split(",");\r
+  foreach(QString s, counterParts) {\r
+    cout << "cont part = " << qPrintable(s) << endl;\r
+    bool ok;\r
+    double val = s.toDouble(&ok);\r
+    if (ok) {\r
+      productionCounter.append(val);\r
+    }\r
+    else if (s.at(0) == '{') {\r
+      s.remove(0,1);\r
+      s.chop(1);\r
+      QStringList gen = s.split(":");\r
+      if (gen.size() != 3) return false;\r
+      int start = 0;\r
+      int nb = 0;\r
+      int step = 0;\r
+      for(int i=0;i<3;i++) {\r
+        bool okVal;\r
+        double result = evaluateExpression(gen.at(i),&okVal);\r
+        if (!okVal) return false;\r
+        if (i==0) start = result;\r
+        else if (i==1) nb = result;\r
+        else if (i==2) step = result;\r
+      }\r
+      for(int j=0;j<nb;j++) {\r
+        productionCounter.append(start+j*step);\r
+      }\r
+    }\r
+    else {\r
+      bool okVal;\r
+      double result = evaluateExpression(s,&okVal);\r
+      \r
+      if (!okVal) return false;\r
+      productionCounter.append(result);      \r
+    }\r
+  }\r
+  foreach(int val, productionCounter) {\r
+    cout << val << ",";\r
+  }\r
+  cout << endl;\r
+  \r
   return true;\r
 }\r
 \r
+QList<char> FunctionalBlock::expandPattern(const QString& pattern, bool* ok) {\r
+  static QString fctName = "FunctionalBlock::expandPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  QList<char> lst;\r
+  QString  p = pattern;\r
+  p.append(')');\r
+  int offset = 0;\r
+  lst = expandPatternRecur(p,&offset,ok);   \r
+  return lst;\r
+}\r
+\r
+QList<char> FunctionalBlock::expandPatternRecur(const QString& pattern, int *offset, bool *ok) {\r
+  \r
+  QList<char> currentGroup; \r
+  \r
+  while ((*offset < pattern.size()) && (pattern.at(*offset) != ')')) {\r
+    \r
+    QChar c = pattern.at(*offset);\r
+    if (c == '(') {\r
+      *offset += 1;\r
+      currentGroup += expandPatternRecur(pattern,offset, ok);\r
+      if (!ok) {\r
+        return currentGroup;\r
+      }\r
+    }\r
+    else if (c == '0') {\r
+      currentGroup.append(0);\r
+    }\r
+    else if (c == '1') {\r
+      currentGroup.append(1);\r
+    }\r
+    else if (c == 'X') {\r
+      currentGroup.append(-1);\r
+    }\r
+    else if (c == '{') {\r
+      *offset += 1;\r
+      QString expr = "";      \r
+      while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {\r
+        expr += pattern.at(*offset);        \r
+        *offset += 1;\r
+      }\r
+      if (*offset == pattern.size()) {\r
+        *ok = false;\r
+        return currentGroup;\r
+      }\r
+      double repeat = evaluateExpression(expr,ok);\r
+      if (!ok) {\r
+        return currentGroup;      \r
+      }            \r
+      // repeat just the last value in currentGroup\r
+      char last = currentGroup.last();      \r
+      //cout << "repeat last char " << repeat << " times : " << (int)last << endl;\r
+      \r
+      for(int i=1;i<(int)repeat;i++) {\r
+        currentGroup += last;\r
+      }\r
+    }    \r
+    *offset += 1;\r
+  }\r
+  \r
+  // must check if after ), there is a {\r
+  if ((*offset < pattern.size()-1) && (pattern.at(*offset+1) == '{')) {\r
+    *offset += 2;\r
+    QString expr = "";      \r
+    while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {\r
+      expr += pattern.at(*offset);        \r
+      *offset += 1;\r
+    }\r
+    if (*offset == pattern.size()) {\r
+      *ok = false;\r
+      return currentGroup;\r
+    }\r
+    double repeat = evaluateExpression(expr,ok);\r
+    if (!ok) {\r
+      return currentGroup;      \r
+    }\r
+    /*\r
+    cout << "repeat last group " << repeat << " times : ";\r
+    foreach (char c, currentGroup) cout <<(int)c;\r
+    cout << endl;  \r
+    */\r
+    QList<char> single = currentGroup;\r
+    for(int i=1;i<(int)repeat;i++) {\r
+      currentGroup += single;\r
+    }    \r
+  }\r
+  //*offset += 1;\r
+  return currentGroup;\r
+}\r
+\r
+double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) {\r
+  static QString fctName = "FunctionalBlock::evaluateExpression()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  *ok = true;\r
+  QHash<QString,double> vars;\r
+  evaluator->setExpression(expression);\r
+  QList<QString> varNames = evaluator->getVariableNames();\r
+  foreach (QString name, varNames) {\r
+    QString paramName = name;\r
+    paramName.remove(0,1);\r
+    BlockParameter* param = reference->getParameterFromName(paramName);    \r
+    if (param == NULL) {\r
+      cerr << "found an unknown parameter in delta"<< endl;\r
+      *ok = false;\r
+      return 0.0;\r
+    }\r
+    bool okVal;\r
+    int val = param->getDoubleValue(&okVal);\r
+    if (!okVal) {\r
+      cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl;\r
+      *ok = false;\r
+      return 0.0;\r
+    }\r
+    vars.insert(name,(double)val);    \r
+  }  \r
+  evaluator->setVariablesValue(vars);\r
+  double result;\r
+  try {\r
+    result = evaluator->evaluate();\r
+  }\r
+  catch(int index) {\r
+    cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;\r
+    *ok = false;\r
+    return 0.0;\r
+  }\r
+  return result;\r
+}\r
+\r
 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
+  static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
   \r
   /* case 1: the block is a generator for which output pattern\r
      must be computed for a nbExec following executions\r
   */\r
   \r
+  \r
   if (nbExec > 0) {\r
+    cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;\r
     foreach(AbstractInterface* iface, getControlOutputs()) {\r
+      FunctionalInterface* connIface = AI_TO_FUN(iface);\r
       QList<char> pattern;\r
-      for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();\r
-      iface->setOutputPattern(pattern);\r
+      for(int i=0;i<nbExec;i++) pattern += connIface->getProductionPattern();\r
+      connIface->setOutputPattern(pattern);\r
     }    \r
   }\r
   else {\r
-    // initialize consumption and production patterns\r
+    cout << "computing output pattern of " << qPrintable(name) << endl;\r
+    \r
+    // initialize consumption and production patterns    \r
     initConsumptionPattern();\r
     initProductionPattern();\r
     \r
@@ -199,7 +429,8 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
     inputPattern = new char*[nbConsumingPorts];\r
     int minLen = -1;\r
     foreach(AbstractInterface* iface, getControlInputs()) {      \r
-      QList<char> in = iface->getConnectedFrom()->getOutputPattern();\r
+      ConnectedInterface* connIface = AI_TO_CON(iface);\r
+      QList<char> in = connIface->getConnectedFrom()->getOutputPattern();\r
       if (minLen == -1) {\r
         minLen = in.size();\r
       }\r
@@ -224,22 +455,26 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
       delete [] inputPattern;\r
       return false;\r
     }\r
+    cout << "input pattern array initialized with min. len " << minLen << endl;\r
     // initialize the output pattern    \r
     char** outputPattern = NULL;\r
     outputPattern = new char*[nbProducingPorts];\r
     int lengthOP = 0;\r
     idIface = 0;\r
     foreach(AbstractInterface* iface, getControlOutputs()) {\r
-      lengthOP = minLen+iface->getProductionPattern().size();\r
+      FunctionalInterface* connIface = AI_TO_FUN(iface);\r
+      lengthOP = minLen+connIface->getProductionPattern().size();\r
       outputPattern[idIface] = new char[lengthOP];\r
       memset(outputPattern[idIface],0,lengthOP);\r
       idIface += 1;\r
     }\r
+    cout << "output pattern array initialized" << endl;\r
     \r
     int clock = 0;\r
     nbExec = 0;\r
     // search for the beginning of the first execution.\r
-    while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;\r
+    while ((clock < minLen) && (! isValidDataGroup(inputPattern,nbConsumingPorts,clock))) clock++;\r
+    cout << "found 1st exec clock: " << clock << endl;\r
     \r
     while (clock < minLen) {\r
       // initialize counters for current execution.\r
@@ -274,7 +509,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
         \r
         // search for PC(m) valid input group in IP\r
         while (ncp < productionCounter.at(m)) {\r
-          if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;\r
+          if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) ncp += 1;\r
           ccp += 1;\r
           gap -= 1;\r
         }\r
@@ -300,12 +535,15 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
     // find the last valid output data group\r
     while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;\r
     \r
+    //for(int i=0;i<lengthOP;i++) cout << (int)(outputPattern[0][i]);\r
+    //cout << endl;\r
     // copy back outputPattern info each interface\r
     idIface = 0;\r
     foreach(AbstractInterface* iface, getControlOutputs()) {\r
+      ConnectedInterface* connIface = AI_TO_CON(iface);\r
       QList<char> pattern;\r
       for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);\r
-      iface->setOutputPattern(pattern);      \r
+      connIface->setOutputPattern(pattern);      \r
       idIface += 1;\r
     }\r
     \r
@@ -358,14 +596,19 @@ void FunctionalBlock::clearProductionPattern() {
 }\r
 \r
 void FunctionalBlock::initConsumptionPattern() {\r
+  static QString fctName = "FunctionalBlock::initConsumptionPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
   if (consumptionPattern != NULL) clearConsumptionPattern();\r
   \r
   nbConsumingPorts = getControlInputs().size();  \r
   int idIface = 0;\r
   consumptionPattern = new char*[nbConsumingPorts];  \r
   foreach(AbstractInterface* iface, getControlInputs()) {\r
-    \r
-    QList<char> in = iface->getConsumptionPattern();\r
+    FunctionalInterface* connIface = AI_TO_FUN(iface);\r
+    QList<char> in = connIface->getConsumptionPattern();\r
     lengthCP = in.size(); // normally, all inputs have the same lenght for CP\r
     consumptionPattern[idIface] = new char[lengthCP];\r
     int i = 0;\r
@@ -375,14 +618,19 @@ void FunctionalBlock::initConsumptionPattern() {
 }\r
 \r
 void FunctionalBlock::initProductionPattern() {\r
+  static QString fctName = "FunctionalBlock::initProductionPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
   if (productionPattern != NULL) clearProductionPattern();\r
   \r
   nbProducingPorts = getControlOutputs().size();  \r
   int idIface = 0;\r
   productionPattern = new char*[nbProducingPorts];  \r
   foreach(AbstractInterface* iface, getControlOutputs()) {\r
-    \r
-    QList<char> in = iface->getProductionPattern();\r
+    FunctionalInterface* connIface = AI_TO_FUN(iface);\r
+    QList<char> in = connIface->getProductionPattern();\r
     lengthPP = in.size(); // normally, all inputs have the same lenght for PP\r
     productionPattern[idIface] = new char[lengthPP];\r
     int i = 0;\r