From 7af5c69c22148510cf8f042552018c9b966860cd Mon Sep 17 00:00:00 2001
From: stephane Domas <stephane.domas@univ-fcomte.fr>
Date: Thu, 18 May 2017 17:01:11 +0200
Subject: [PATCH 1/1] modified pattern to use only QMap

---
 ConnectedInterface.cpp                   |  16 +-
 ConnectedInterface.h                     |   9 +-
 Dispatcher.cpp                           |   2 +-
 FunctionalBlock.cpp                      | 355 +++++++++++------------
 FunctionalBlock.h                        |  85 ++++--
 FunctionalInterface.h                    |  13 +-
 GroupBlock.cpp                           |   6 +-
 GroupBlock.h                             |   7 +
 blast.creator.user                       |   8 +-
 lib/implementations/average-Nx3_impl.xml |   2 +-
 lib/implementations/impls.bmf            | Bin 2886 -> 2912 bytes
 11 files changed, 285 insertions(+), 218 deletions(-)

diff --git a/ConnectedInterface.cpp b/ConnectedInterface.cpp
index c053aad..948388a 100644
--- a/ConnectedInterface.cpp
+++ b/ConnectedInterface.cpp
@@ -6,15 +6,25 @@
 
 ConnectedInterface::ConnectedInterface(AbstractBlock* _owner) : AbstractInterface(_owner) {
   connectedFrom = NULL;
+  outputPattern = NULL;
+      
 }
 
 ConnectedInterface::ConnectedInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose) : AbstractInterface(_owner, _name, _type, _width, _direction, _purpose) {
   connectedFrom = NULL;
+  outputPattern = NULL;
 }
 
+ConnectedInterface::~ConnectedInterface() {
+  if (outputPattern != NULL) delete outputPattern;
+}
+
+/* NB/ became useless since disconnectTo does the job
+ 
 void ConnectedInterface::removeConnectedTo(ConnectedInterface *iface) {
-  connectedTo.removeOne(iface);
+  connectedTo.removeAll(iface);
 }
+*/
 
 void ConnectedInterface::clearConnections() {
   connectedFrom = NULL;
@@ -25,6 +35,10 @@ void ConnectedInterface::clearConnectedTo() {
   connectedTo.clear();
 }
 
+void ConnectedInterface::setOutputPattern(QList<char>* pattern) {
+  if (outputPattern != NULL) delete outputPattern;
+  outputPattern = pattern; 
+}
 void ConnectedInterface::connectTo(ConnectedInterface *iface) {
   
   connectedTo.append(iface);
diff --git a/ConnectedInterface.h b/ConnectedInterface.h
index 84066a6..7866a8f 100644
--- a/ConnectedInterface.h
+++ b/ConnectedInterface.h
@@ -24,14 +24,15 @@ public :
 
   ConnectedInterface(AbstractBlock* _owner);
   ConnectedInterface(AbstractBlock* _owner, const QString& _name, const QString& _type, const QString& _width, int _direction, int _purpose);
+  ~ConnectedInterface();
   
   // getters
   inline QList<ConnectedInterface*> getConnectedTo() { return connectedTo;}
   inline ConnectedInterface* getConnectedFrom() { return connectedFrom;}
-  inline QList<char> getOutputPattern() { return outputPattern; }  
+  inline QList<char>* getOutputPattern() { return outputPattern; }  
 
   // setters
-  inline void setOutputPattern(QList<char> pattern) { outputPattern = pattern; }
+  void setOutputPattern(QList<char>* pattern);
 
   // testers
   inline bool isConnectedTo(){return connectedTo.length() != 0;}
@@ -47,7 +48,7 @@ public :
   ConnectedInterface* getConnectionFromParentGroup();
 
   virtual AbstractInterface *clone() = 0;  
-  void removeConnectedTo(ConnectedInterface *inter);
+  //void removeConnectedTo(ConnectedInterface *inter);
 
   virtual void clearConnectedTo();
   inline void clearConnectedFrom() { connectedFrom = NULL; }
@@ -71,7 +72,7 @@ protected:
   ConnectedInterface* connectedFrom;  
   
   // patterns  
-  QList<char> outputPattern; //! only usefull for output interfaces
+  QList<char>* outputPattern; //! only usefull for output interfaces
 };
 
 
diff --git a/Dispatcher.cpp b/Dispatcher.cpp
index 4cd112d..ee72743 100644
--- a/Dispatcher.cpp
+++ b/Dispatcher.cpp
@@ -344,7 +344,7 @@ void Dispatcher::showPatterns(InterfaceItem *item) {
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
   ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
-  foreach(char c, iface->getOutputPattern()) {
+  foreach(char c, *(iface->getOutputPattern())) {
     cout << (int)c;
   }
   cout << endl;
diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp
index 0db21c4..23d43b9 100644
--- a/FunctionalBlock.cpp
+++ b/FunctionalBlock.cpp
@@ -14,12 +14,7 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference
   reference = _reference;
   parent = _parent;
   name = reference->getName();
-  consumptionPattern = NULL;
-  lengthCP = 0;
-  nbConsumingPorts = 0;
-  productionPattern = NULL;
-  lengthPP = 0;
-  nbProducingPorts = 0;
+
   if (reference->getImplementations().isEmpty()) {
     implementation = NULL;
     cout << "block has no implementation" << endl;
@@ -169,16 +164,10 @@ bool FunctionalBlock::createConsumptionPattern() {
       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;
       return false;
     }
-    QList<char> pattern = expandPattern(consPattern.value(refName),&ok);    
+    QList<char>* pattern = expandPattern(consPattern.value(refName),&ok);    
     
     if (!ok) return false;
-    connIface->setConsumptionPattern(pattern);
-    cout << qPrintable(refName) << " consumption pattern = ";
-    foreach(char c, pattern) {
-      cout << (int)c << " ";
-    }
-    cout << endl;
-    
+    consumptionPattern.insert(connIface,pattern);        
   }        
   return true;
 }
@@ -199,15 +188,9 @@ bool FunctionalBlock::createProductionPattern() {
       cerr << "no production pattern for reference interface " << qPrintable(refName) << endl;
       return false;
     }
-    QList<char> pattern = expandPattern(prodPattern.value(refName),&ok);
+    QList<char>* pattern = expandPattern(prodPattern.value(refName),&ok);
     if (!ok) return false;
-    connIface->setProductionPattern(pattern);
-    cout << qPrintable(refName) << " production pattern = ";
-    foreach(char c, pattern) {
-      cout << (int)c << " ";
-    }
-    cout << endl;
-    
+    productionPattern.insert(connIface,pattern);    
   }    
   return true;
 }
@@ -262,97 +245,96 @@ bool FunctionalBlock::createProductionCounter() {
   return true;
 }
 
-QList<char> FunctionalBlock::expandPattern(const QString& pattern, bool* ok) {
+QList<char>* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) {
   static QString fctName = "FunctionalBlock::expandPattern()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
   
   QList<char> lst;
-  QString  p = pattern;
+  QString  p = patternIn;
   p.append(')');
   int offset = 0;
-  lst = expandPatternRecur(p,&offset,ok);   
-  return lst;
+  QList<char>* patternOut = new QList<char>();
+  expandPatternRecur(p,&offset,ok,patternOut);   
+  return patternOut;
 }
 
-QList<char> FunctionalBlock::expandPatternRecur(const QString& pattern, int *offset, bool *ok) {
-  
-  QList<char> currentGroup; 
+void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, bool *ok, QList<char>* patternOut) {  
   
-  while ((*offset < pattern.size()) && (pattern.at(*offset) != ')')) {
+  while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) {
     
-    QChar c = pattern.at(*offset);
+    QChar c = patternIn.at(*offset);
     if (c == '(') {
       *offset += 1;
-      currentGroup += expandPatternRecur(pattern,offset, ok);
+      expandPatternRecur(patternIn,offset, ok, patternOut);
       if (!ok) {
-        return currentGroup;
+        return;
       }
     }
     else if (c == '0') {
-      currentGroup.append(0);
+      patternOut->append(0);
     }
     else if (c == '1') {
-      currentGroup.append(1);
+      patternOut->append(1);
     }
     else if (c == 'X') {
-      currentGroup.append(-1);
+      patternOut->append(-1);
     }
     else if (c == '{') {
       *offset += 1;
       QString expr = "";      
-      while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {
-        expr += pattern.at(*offset);        
+      while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {
+        expr += patternIn.at(*offset);        
         *offset += 1;
       }
-      if (*offset == pattern.size()) {
+      if (*offset == patternIn.size()) {
         *ok = false;
-        return currentGroup;
+        return;
       }
       double repeat = evaluateExpression(expr,ok);
       if (!ok) {
-        return currentGroup;      
+        return;      
       }            
       // repeat just the last value in currentGroup
-      char last = currentGroup.last();      
+      char last = patternOut->last();      
       //cout << "repeat last char " << repeat << " times : " << (int)last << endl;
       
       for(int i=1;i<(int)repeat;i++) {
-        currentGroup += last;
+        patternOut->append(last);
       }
     }    
     *offset += 1;
   }
   
   // must check if after ), there is a {
-  if ((*offset < pattern.size()-1) && (pattern.at(*offset+1) == '{')) {
+  if ((*offset < patternIn.size()-1) && (patternIn.at(*offset+1) == '{')) {
     *offset += 2;
     QString expr = "";      
-    while ((*offset < pattern.size()) && (pattern.at(*offset) != '}')) {
-      expr += pattern.at(*offset);        
+    while ((*offset < patternIn.size()) && (patternIn.at(*offset) != '}')) {
+      expr += patternIn.at(*offset);        
       *offset += 1;
     }
-    if (*offset == pattern.size()) {
+    if (*offset == patternIn.size()) {
       *ok = false;
-      return currentGroup;
+      return;
     }
     double repeat = evaluateExpression(expr,ok);
     if (!ok) {
-      return currentGroup;      
+      return;      
     }
     /*
     cout << "repeat last group " << repeat << " times : ";
     foreach (char c, currentGroup) cout <<(int)c;
     cout << endl;  
     */
-    QList<char> single = currentGroup;
+    QList<char> single = *patternOut;
     for(int i=1;i<(int)repeat;i++) {
-      currentGroup += single;
+      patternOut->append(single);
     }    
   }
   //*offset += 1;
-  return currentGroup;
+  return;
 }
 
 double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) {
@@ -382,7 +364,8 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok)
       return 0.0;
     }
     vars.insert(name,(double)val);    
-  }  
+  }
+  
   evaluator->setVariablesValue(vars);
   double result;
   try {
@@ -411,69 +394,72 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
     cout << "computing output pattern of " << qPrintable(name) << " for " << nbExec << " executions" << endl;
     foreach(AbstractInterface* iface, getControlOutputs()) {
       FunctionalInterface* connIface = AI_TO_FUN(iface);
-      QList<char> pattern;
-      for(int i=0;i<nbExec;i++) pattern += connIface->getProductionPattern();
+      // create output pattern
+      QList<char>* pp = productionPattern.value(connIface);
+      QList<char>* pattern = new QList<char>(*pp);
+      for(int i=1;i<nbExec;i++) pattern->append(*pp);
+      // assign pattern to interface
       connIface->setOutputPattern(pattern);
-    }    
+      // store it in QMap
+      outputPattern.insert(connIface,pattern);      
+    }
   }
   else {
     cout << "computing output pattern of " << qPrintable(name) << endl;
     
-    // initialize consumption and production patterns    
-    initConsumptionPattern();
-    initProductionPattern();
-    
-    // collect the input patterns for each input    
-    char** inputPattern = NULL;
-    int idIface = 0;
-    inputPattern = new char*[nbConsumingPorts];
+    // collect the input patterns for each input 
+    QMap<AbstractInterface*,QList<char>* > inputPattern;    
     int minLen = -1;
     foreach(AbstractInterface* iface, getControlInputs()) {      
       ConnectedInterface* connIface = AI_TO_CON(iface);
-      QList<char> in = connIface->getConnectedFrom()->getOutputPattern();
+      QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
       if (minLen == -1) {
-        minLen = in.size();
+        minLen = out->size();
       }
       else {
-        if (in.size() < minLen) minLen = in.size();
+        if (out->size() < minLen) minLen = out->size();
       }
-      if (in.size() > 0) {
-        inputPattern[idIface] = new char[in.size()];
-        int i = 0;
-        foreach(char c, in) inputPattern[idIface][i++] = c;
+      if (out->size() > 0) {
+        QList<char>* in = new QList<char>(*out);
+        foreach(char c, *in) {
+          cout << (int)c;
+        }
+        cout << endl;
+
+        inputPattern.insert(connIface,in);
       }
       else {
-        inputPattern[idIface] = NULL;
-      }
-      idIface += 1;      
+        inputPattern.insert(connIface,NULL);
+      }      
     }
-    // if some patterns are not available, ens now, returning false
+    // if some patterns are not available, end now, returning false
     if (minLen == 0) {
-      for(int i=0;i<nbConsumingPorts; i++) {
-        if (inputPattern[i] != NULL) delete [] inputPattern[i];
-      }
-      delete [] inputPattern;
+      QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);
+      while (iterI.hasNext()) {
+        iterI.next();
+        QList<char>* pattern = iterI.value();        
+        if (pattern != NULL) delete pattern;
+      }     
       return false;
     }
     cout << "input pattern array initialized with min. len " << minLen << endl;
+    
     // initialize the output pattern    
-    char** outputPattern = NULL;
-    outputPattern = new char*[nbProducingPorts];
     int lengthOP = 0;
-    idIface = 0;
     foreach(AbstractInterface* iface, getControlOutputs()) {
-      FunctionalInterface* connIface = AI_TO_FUN(iface);
-      lengthOP = minLen+connIface->getProductionPattern().size();
-      outputPattern[idIface] = new char[lengthOP];
-      memset(outputPattern[idIface],0,lengthOP);
-      idIface += 1;
+      FunctionalInterface* connIface = AI_TO_FUN(iface);      
+      lengthOP = minLen+productionPattern.value(connIface)->size();
+      QList<char>* pattern = new QList<char>();
+      for(int i=0;i<lengthOP;i++) pattern->append(0);
+      connIface->setOutputPattern(pattern);
+      outputPattern.insert(connIface,pattern);
     }
     cout << "output pattern array initialized" << endl;
     
     int clock = 0;
     nbExec = 0;
     // search for the beginning of the first execution.
-    while ((clock < minLen) && (! isValidDataGroup(inputPattern,nbConsumingPorts,clock))) clock++;
+    while ((clock < minLen) && (! isValidDataGroup(inputPattern,clock))) clock++;
     cout << "found 1st exec clock: " << clock << endl;
     
     while (clock < minLen) {
@@ -487,7 +473,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
       bool cannotCompleteExec = false;
       for(int m=0;m<productionCounter.size();m++) {
         // search for the first production in PP
-        while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {
+        while (!isValidDataGroup(productionPattern,p)) {
           p += 1;
           o += 1;
         }
@@ -495,7 +481,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
         // search for PC(m) valid input group in IP
         while (nip < productionCounter.at(m)) {
           if (clock+cip < minLen) {
-            if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;
+            if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;
             cip += 1;
             gap += 1;
           }
@@ -503,18 +489,18 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
             cannotCompleteExec = true;
             break;
           }        
-        }
+        }        
         
         if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
         
         // search for PC(m) valid input group in IP
         while (ncp < productionCounter.at(m)) {
-          if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) ncp += 1;
+          if (isValidDataGroup(consumptionPattern,ccp)) ncp += 1;
           ccp += 1;
           gap -= 1;
         }
         o += gap; // to take into acocunt of extra null columns
-        combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);
+        combinePatterns(productionPattern,p,outputPattern,clock+o);
         p += 1;
         o += 1;
       }
@@ -528,113 +514,126 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
       clock += 1;      
       nip = 0;
       while ((clock < minLen) && (nip < delta)) {
-        if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;
+        if (isValidDataGroup(inputPattern,clock)) nip += 1;
         if (nip < delta) clock += 1;
       }
+      cout << "found exec " << nbExec << " at clock: " << clock << endl;
     }
     // find the last valid output data group
-    while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;
-    
-    //for(int i=0;i<lengthOP;i++) cout << (int)(outputPattern[0][i]);
-    //cout << endl;
-    // copy back outputPattern info each interface
-    idIface = 0;
-    foreach(AbstractInterface* iface, getControlOutputs()) {
-      ConnectedInterface* connIface = AI_TO_CON(iface);
-      QList<char> pattern;
-      for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);
-      connIface->setOutputPattern(pattern);      
-      idIface += 1;
-    }
-    
-    // clear inputPattern and outputPattern
-    for(int i=0;i<nbConsumingPorts; i++) {
-      delete [] inputPattern[i];
-    }
-    delete [] inputPattern;
-    for(int i=0;i<nbProducingPorts; i++) {
-      delete [] outputPattern[i];
+    while(! isValidDataGroup(outputPattern,lengthOP-1)) {
+      removeDataGroup(outputPattern,lengthOP-1);
+      lengthOP -= 1;
     }
-    delete [] outputPattern;
+
+    // clear input pattern    
+    QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);
+    while (iterI.hasNext()) {
+      iterI.next();
+      QList<char>* pattern = iterI.value();        
+      if (pattern != NULL) delete pattern;
+    }     
   }
   return true;
 }
 
-bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {
-  
-  for(int i=0;i<nbPorts;i++) {
-    if (pattern[i][clock] == 1) return true;
+bool FunctionalBlock::canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {
+  if (patternSrc.size() != patternDest.size()) return false;
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
+  QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
+  while (iterSrc.hasNext()) {
+    iterSrc.next();
+    iterDest.next();    
+    QList<char>* srcPat = iterSrc.value();
+    QList<char>* destPat = iterDest.value();
+    if (srcCol >= srcPat->size()) return false;
+    if (destCol >= destPat->size()) return false;
+    if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return false;
+    if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return false;
   }
-  return false;  
+  return true;
 }
 
-void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {
-  
-  for (int i=0;i<nbCols;i++) {
-    for(int j=0;j<nbPorts;j++) {
-      patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];
+void FunctionalBlock::combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol) {
+  if (patternSrc.size() != patternDest.size()) return;
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
+  QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
+  while (iterSrc.hasNext()) {
+    iterSrc.next();
+    iterDest.next();    
+    QList<char>* srcPat = iterSrc.value();
+    QList<char>* destPat = iterDest.value();
+    if (srcCol >= srcPat->size()) return;
+    if (destCol >= destPat->size()) return;
+    if ((srcPat->at(srcCol) == -1) && (destPat->at(destCol) == 1)) return;
+    if ((srcPat->at(srcCol) == 1) && (destPat->at(destCol) == -1)) return;    
+    destPat->replace(destCol,destPat->at(destCol) | srcPat->at(srcCol));
+  }  
+}
+
+void FunctionalBlock::appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols) {
+  if (patternSrc.size() != patternDest.size()) return;
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(patternSrc);
+  QMapIterator<AbstractInterface*, QList<char>* > iterDest(patternDest);
+  while (iterSrc.hasNext()) {
+    iterSrc.next();
+    iterDest.next();    
+    QList<char>* srcPat = iterSrc.value();
+    QList<char>* destPat = iterDest.value();    
+    int i=0;
+    while ((srcCol+i < srcPat->size()) && (i<nbCols)) {
+      destPat->append(srcPat->at(srcCol+i));
+      i++;
     }
-  }
-  
+  }  
 }
 
-void FunctionalBlock::clearConsumptionPattern() {
-  if (consumptionPattern == NULL) return;
-  
-  for(int i=0;i<nbConsumingPorts; i++) {
-    delete [] consumptionPattern[i];
+void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  
+  while (iterSrc.hasNext()) {
+    iterSrc.next();    
+    QList<char>* srcPat = iterSrc.value();
+    if (offset < srcPat->size()) {
+      srcPat->removeAt(offset);
+    }
   }
-  delete [] consumptionPattern;      
 }
 
-void FunctionalBlock::clearProductionPattern() {
-  if (productionPattern == NULL) return;
-  for(int i=0;i<nbProducingPorts;i++) {
-    delete [] productionPattern[i];
+bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  
+  while (iterSrc.hasNext()) {
+    iterSrc.next();    
+    QList<char>* srcPat = iterSrc.value();
+    if (offset >= srcPat->size()) return false;
+    if (srcPat->at(offset) == 1) return true;
   }
-  delete [] productionPattern;
+  return false;
 }
 
-void FunctionalBlock::initConsumptionPattern() {
-  static QString fctName = "FunctionalBlock::initConsumptionPattern()";
-#ifdef DEBUG_FCTNAME
-  cout << "call to " << qPrintable(fctName) << endl;
-#endif
-  
-  if (consumptionPattern != NULL) clearConsumptionPattern();
-  
-  nbConsumingPorts = getControlInputs().size();  
-  int idIface = 0;
-  consumptionPattern = new char*[nbConsumingPorts];  
-  foreach(AbstractInterface* iface, getControlInputs()) {
-    FunctionalInterface* connIface = AI_TO_FUN(iface);
-    QList<char> in = connIface->getConsumptionPattern();
-    lengthCP = in.size(); // normally, all inputs have the same lenght for CP
-    consumptionPattern[idIface] = new char[lengthCP];
-    int i = 0;
-    foreach(char c, in) consumptionPattern[idIface][i++] = c;
-    idIface += 1;    
+bool FunctionalBlock::isOnlyXDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  
+  while (iterSrc.hasNext()) {
+    iterSrc.next();    
+    QList<char>* srcPat = iterSrc.value();
+    if (offset >= srcPat->size()) return false;
+    if (srcPat->at(offset) != -1) return false;
   }
+  return true;  
 }
 
-void FunctionalBlock::initProductionPattern() {
-  static QString fctName = "FunctionalBlock::initProductionPattern()";
-#ifdef DEBUG_FCTNAME
-  cout << "call to " << qPrintable(fctName) << endl;
-#endif
-  
-  if (productionPattern != NULL) clearProductionPattern();
-  
-  nbProducingPorts = getControlOutputs().size();  
-  int idIface = 0;
-  productionPattern = new char*[nbProducingPorts];  
-  foreach(AbstractInterface* iface, getControlOutputs()) {
-    FunctionalInterface* connIface = AI_TO_FUN(iface);
-    QList<char> in = connIface->getProductionPattern();
-    lengthPP = in.size(); // normally, all inputs have the same lenght for PP
-    productionPattern[idIface] = new char[lengthPP];
-    int i = 0;
-    foreach(char c, in) productionPattern[idIface][i++] = c;
-    idIface += 1;    
+void FunctionalBlock::clearConsumptionPattern() {
+  QMapIterator<AbstractInterface*, QList<char>* > iterP(consumptionPattern);  
+  while (iterP.hasNext()) {
+    iterP.next();
+    QList<char>* pattern = iterP.value();
+    if (pattern != NULL) delete pattern;
   }
-}
+}  
+
+void FunctionalBlock::clearProductionPattern() {
+  QMapIterator<AbstractInterface*, QList<char>* > iterP(productionPattern);  
+  while (iterP.hasNext()) {
+    iterP.next();
+    QList<char>* pattern = iterP.value();
+    if (pattern != NULL) delete pattern;
+  }
+}  
diff --git a/FunctionalBlock.h b/FunctionalBlock.h
index b6ac65f..2cf9a5a 100644
--- a/FunctionalBlock.h
+++ b/FunctionalBlock.h
@@ -57,40 +57,83 @@ public:
   bool createConsumptionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation
   bool createProductionPattern(); // initialize a QList<char> for each interface from patterns defined in implementation
   bool createProductionCounter(); // initialize a QList<int> from counter defined in implementation
-  void initConsumptionPattern(); // initialize a char** from patterns defined for each interface
-  void initProductionPattern(); // initialize a char** from patterns defined for each interface
   void clearConsumptionPattern();
   void clearProductionPattern();
   bool computeOutputPattern(int nbExec = -1);
   
 private:  
-  // patterns  
-  bool isValidDataGroup(char** pattern, int nbPorts, int clock);
+  // patterns    
   double evaluateExpression(const QString& expression, bool* ok);
-  QList<char> expandPattern(const QString& pattern, bool* ok);
-  QList<char> expandPatternRecur(const QString& pattern, int* offset, bool* ok);
+  QList<char>* expandPattern(const QString& patternIn, bool* ok);
+  void expandPatternRecur(const QString& patternIn, int* offset, bool* ok, QList<char> *patternOut);
+  /*!
+   * \brief canCombinePatterns
+   * \param patternSrc the pattern that must be combined with patternDest (patternDest = patternDest OR patternSrc)  
+   * \param srcCol the column index within patternSrc
+   * \param patternDest the pattern that is modified by the combination (patternDest = patternDest OR patternSrc)
+   * \param destCol the column index within patternDest  
+   * \return true if the combination is possible, and false else (e.g. when X1 must be combined with 11)
+   * NB: if src/destCol are outside the range of the list, false is returned.   
+   */
+  bool canCombinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol);
   /*!
    * \brief combinePatterns
    * \param patternSrc the pattern that must be combined with patternDest (patternDest = patternDest OR patternSrc)  
    * \param srcCol the column index within patternSrc
    * \param patternDest the pattern that is modified by the combination (patternDest = patternDest OR patternSrc)
-   * \param destClock the column index within patternDest
-   * \param nbCols the numer of columns to combine
-   * \param nbPorts the number of rows in both patterns
-   * BEWARE: no check is done if nbCols is consistent with the real length of both patterns, thus an access outside
-   * the patterns is possible.
+   * \param destCol the column index within patternDest      
+   * BEWARE: this method returns as soons as there is an acces problem (i.e. out of list range, impossible combine, ...)
+   leaving the dest pattern in an inconsistent state. Thus, it is a good idea to call canCombine before.
    */
-  void combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts );
-
-  QList<int> productionCounter; //! only usefull for output interfaces
-  int delta;
+  void combinePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int destCol);
+  /*!
+   * \brief appendToPattern
+   * \param patternSrc the pattern that must be appended to patternDest
+   * \param srcCol the column index within patternSrc
+   * \param patternDest the pattern that is modified by the append   
+   * \param nbCols the numer of columns to append   
+   * BEWARE: if nbCols is not consistent with the real length of src pattern, there may be less that nbCols
+   * that will be appended
+   */
+  void appendToPattern(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, QMap<AbstractInterface*, QList<char>* > patternDest, int nbCols);
+  /*!
+  * \brief removeDataGroup
+  * \param pattern the pattern for which a column is removed
+  * \param offset the index of the column to remove 
+  */
+  void removeDataGroup(QMap<AbstractInterface*, QList<char>* >& pattern, int offset);
+  /*!
+  * \brief isValidGroup
+  * \param pattern the pattern to test
+  * \param offset the column to test
+  * isValidGroup checks if there is at least one 1 in the column offset of pattern.
+  */
+  bool isValidDataGroup(const QMap<AbstractInterface*, QList<char>* >& pattern, int offset);
+  /*!
+  * \brief isOnlyXGroup
+  * \param pattern the pattern to test
+  * \param offset the column to test
+  * isOnlyXGroup checks if there is only X in the column offset of pattern.
+  */
+  bool isOnlyXDataGroup(const QMap<AbstractInterface*, QList<char>* >& pattern, int offset);
+  /*!
+  * \brief shifRightPattern
+  * \param pattern the pattern to shift
+  * \param offset the column where to shift
+  * shiftRightPattern insert a null colmun in pattern, which leads to shift right the pattern at offset.
+  * this method is used during admittance generation
+  */
+  void shiftRightPattern(const QMap<AbstractInterface*, QList<char>* >& pattern, int offset);
+
+  QMap<AbstractInterface*, QList<char>* > consumptionPattern;
+  QMap<AbstractInterface*, QString > admittance; // the admittance expressed as prologue-cyclic part-eppilogue
+  QMap<AbstractInterface*, QList<char>* > admittanceExpanded; // the admittance expanded by taking into account nb exec.
+  QMap<AbstractInterface*, QList<char>* > productionPattern;
+  QMap<AbstractInterface*, QList<char>* > outputPattern; // CAUTION: the QList<char>* must also be stored in the outputPattern attributes of AbstractInterface
+  QList<int> productionCounter; //! only usefull for control output interfaces
   
-  char** consumptionPattern;
-  int nbConsumingPorts;
-  int lengthCP;
-  char** productionPattern;
-  int nbProducingPorts;
-  int lengthPP;
+  int delta;
+    
   ArithmeticEvaluator* evaluator;
   
   ReferenceBlock* reference;
diff --git a/FunctionalInterface.h b/FunctionalInterface.h
index b87e2c7..43f31c3 100644
--- a/FunctionalInterface.h
+++ b/FunctionalInterface.h
@@ -35,12 +35,12 @@ public :
 
   // getters
   inline ReferenceInterface* getReference() { return reference; }
-  inline QList<char> getConsumptionPattern() { return consumptionPattern; }
-  inline QList<char> getProductionPattern() { return productionPattern; }  
+  //inline QList<char>* getConsumptionPattern() { return consumptionPattern; }
+  //inline QList<char>* getProductionPattern() { return productionPattern; }  
 
   // setters
-  inline void setConsumptionPattern(QList<char> pattern) { consumptionPattern = pattern; }
-  inline void setProductionPattern(QList<char> pattern) { productionPattern = pattern; }  
+  //inline void setConsumptionPattern(QList<char>* pattern) { consumptionPattern = pattern; }
+  //inline void setProductionPattern(QList<char>* pattern) { productionPattern = pattern; }  
 
   // testers
   bool isFunctionalInterface();
@@ -59,8 +59,9 @@ private:
   ReferenceInterface* reference;  
   
   //patterns
-  QList<char> consumptionPattern; //! only usefull for input interfaces
-  QList<char> productionPattern; //! only usefull for output interfaces  
+  //QList<char>* consumptionPattern; //! only usefull for input interfaces
+  //QList<char>* productionPattern; //! only usefull for output interfaces  
+  //QString admittance; //! only usefull for input interfaces  
 };
 
 #endif // __FUNCTIONALINTERFACE_H__
diff --git a/GroupBlock.cpp b/GroupBlock.cpp
index 474d5dc..2fc3012 100644
--- a/GroupBlock.cpp
+++ b/GroupBlock.cpp
@@ -108,7 +108,8 @@ void GroupBlock::removeGenericParameter(QString name) {
 void GroupBlock::initInputPattern() {
   foreach(AbstractInterface* iface, getControlInputs()) {
     ConnectedInterface* connIface = AI_TO_CON(iface);
-    connIface->setOutputPattern(connIface->getConnectedFrom()->getOutputPattern());    
+    QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));    
+    connIface->setOutputPattern(pattern);    
   }  
 }
 
@@ -185,7 +186,8 @@ bool GroupBlock::computeOutputPattern(int nbExec) {
   if (canCompute) {
     foreach(AbstractInterface* iface, getControlOutputs()) {
       ConnectedInterface* connIface = AI_TO_CON(iface);
-      connIface->setOutputPattern(connIface->getConnectedFrom()->getOutputPattern());    
+      QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
+      connIface->setOutputPattern(pattern);    
     }
     setPatternComputed(true);
   }
diff --git a/GroupBlock.h b/GroupBlock.h
index 593b854..4a147ab 100644
--- a/GroupBlock.h
+++ b/GroupBlock.h
@@ -46,6 +46,13 @@ public:
   
 private:    
   // patterns  
+  /* NB: in opposition to FunctionalBlock, the input pattern and output pattern of a block
+     is not computed but just deduced from the output pattern of functional interfaces that
+     are connected to some block interfaces. Thus, there is no need to have an outputPattern QMap linking
+     interfaces and patterns as in FunctionalBlock.
+     Thus, the output patterns are directly set/retrieved from interfaces.
+    
+   */
   /*!
    * \brief initInputPattern
    * Since input GroupInterface are just tunnels to input interfaces of inner blocks, they must
diff --git a/blast.creator.user b/blast.creator.user
index d213478..dc3af4e 100755
--- a/blast.creator.user
+++ b/blast.creator.user
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 3.2.1, 2017-05-14T21:44:23. -->
+<!-- Written by QtCreator 3.2.1, 2017-05-18T16:26:09. -->
 <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>
@@ -60,12 +60,12 @@
   <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">
diff --git a/lib/implementations/average-Nx3_impl.xml b/lib/implementations/average-Nx3_impl.xml
index 4c1457d..981529b 100644
--- a/lib/implementations/average-Nx3_impl.xml
+++ b/lib/implementations/average-Nx3_impl.xml
@@ -28,7 +28,7 @@
     <consumption>
       <input name="data_i_enb" pattern="1{$nb_data}" />
     </consumption>
-    <production counter="{2:$nb_data:1}">
+    <production counter="{2:$nb_data-1:1},$nb_data-1">
       <output name="data_o_enb" pattern="0001{$nb_data}" />
     </production>
   </patterns>
diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf
index d43a935111c63cb5fee4e6a04d0c141242216977..f108eac57120f7b7bb773d4b8eb71ec7ea70fa2d 100644
GIT binary patch
delta 86
zcmX>m_CSn<fq^?_BFlT$76t}}SrY|HC+9L=F*jqVW-wx~Vo+hoV@P6%XGmd4WGDe*
VT?Rv-s3AiwgAO*i&2daGH~?@K643wv

delta 60
zcmaDLc1(<gfq~m;BFlT$ECvRKSrY|HC+9L=k(FVnW-wx~Vo+hoV@P6%XGmd4WGDe*
OD+WV`+RYVAFE{|s3=XaU

-- 
2.39.5