From: domas stephane <sdomas@info-s2-01.iut-bm.univ-fcomte.fr>
Date: Mon, 22 May 2017 17:37:09 +0000 (+0200)
Subject: modifying pattern methods to throw exceptions
X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain/7b1c7e44123b9b2626205a89e27b2a4712ea30c6?ds=inline;hp=c8c1e24dac94abfacb78fb3b661c9a5dbbb0d86a

modifying pattern methods to throw exceptions
---

diff --git a/AbstractBlock.h b/AbstractBlock.h
index aee8c99..2bb2717 100644
--- a/AbstractBlock.h
+++ b/AbstractBlock.h
@@ -70,8 +70,8 @@ public:
   BlockParameter* getParameterFromName(QString name);
 
   // patterns
-  virtual bool checkInputPatternCompatibility() = 0;
-  virtual bool computeOutputPattern(int nbExec = -1) = 0;
+  virtual void checkInputPatternCompatibility() throw(Exception) = 0;
+  virtual void computeOutputPattern(int nbExec = -1) throw(Exception) = 0;
   
 protected:
 
diff --git a/Exception.cpp b/Exception.cpp
index 9093e49..a051e7a 100644
--- a/Exception.cpp
+++ b/Exception.cpp
@@ -34,6 +34,21 @@ QString Exception::getDefaultMessage() {
   case BLOCKITEM_INVALID_TYPE : ret = tr("A parameter of type AbstractBlockItem* is used with an incorrect instance type."); break;
   case WIDTHS_NOT_EQUALS : ret = tr("Two interfaces are connected but don't have the same widths."); break;
   case INVALID_VALUE : ret = tr("parameter value is not correct (e.g. not numeric, invalid other parameter name, ...)."); break;
+  case INVALID_REFBLOCK_USE : ret = tr("a reference block is used during pattern computations"); break;
+  case INVALID_DELTA_CP : ret = tr("delta and CP are not consistent"); break;
+  case EVAL_PARAM_UNKNOWN : ret = tr("a variable used in an expression is not defined as a block parameter"); break;
+  case EVAL_PARAM_NOVALUE : ret = tr("can't get the double value of a block parameter"); break;
+  case EVAL_INVALID_EXPR : ret = tr("invalid arithmetic expression (in a block parameter/pattern)"); break;    
+  case INVALID_IFACE_PATTERN : ret = tr("the pattern of an interface is invalid (not correct grammar)"); break;
+  case INVALID_IFACE_PC : ret = tr("the production counter of an interface is invalid (not correct grammar)"); break;    
+  case INVALID_IFACE_CP_LENGTH : ret = tr("the size of CP for an interface differs from others"); break;
+  case NO_IFACE_CP : ret = tr("an interface has no CP defined in reference block"); break;    
+  case INVALID_IFACE_PP_LENGTH : ret = tr("the size of PP for an interface differs from others"); break;
+  case NO_IFACE_PP : ret = tr("an interface has no PP defined in reference block"); break;    
+  case NO_IFACE_IP : ret = tr("an interface has no IP"); break;
+  case IP_AP_NOTCOMPAT : ret = tr("IP and AP not compatible"); break;
+  case IP_END_NULLCOL : ret = tr("IP ends with anull column (normally not possible during compat. check)"); break;
+  case AP_TOO_SHORT : ret = tr("AP has been badly computed, leading to a AP shorter than needed (NB: it is an abnormal case)"); break;
   }
 
   return ret;
diff --git a/Exception.h b/Exception.h
index c65ed5a..3972d4e 100644
--- a/Exception.h
+++ b/Exception.h
@@ -58,6 +58,29 @@ supp. infos : saved in UTF-8 [éè]
 // exceptions for VHDL generation
 #define INVALID_VALUE 5001
 
+// exception for patterns
+#define INVALID_REFBLOCK_USE 10001
+#define INVALID_DELTA_CP 10002 // delta and CP are not consistent (NB: used during admittance computation)
+
+#define EVAL_PARAM_UNKNOWN 10101 // a variable used in an expression is not defined as a block parameter
+#define EVAL_PARAM_NOVALUE 10102 // can't get the double value of a block parameter
+#define EVAL_INVALID_EXPR 10103 // invalid arithmetic expression (in a block parameter/pattern)
+
+#define INVALID_IFACE_PATTERN 10201 // the pattern of an interface is invalid (not correct grammar)
+#define INVALID_IFACE_PC 10202 // the production counter of an interface is invalid (not correct grammar)
+
+#define INVALID_IFACE_CP_LENGTH 10301 // the size of CP for an interface differs from others
+#define NO_IFACE_CP 10302 // an interface has no CP defined in reference block
+
+#define INVALID_IFACE_PP_LENGTH 10401 // the size of PP for an interface differs from others
+#define NO_IFACE_PP 10402 // an interface has no PP defined in reference block
+
+#define NO_IFACE_IP 10501 // an interface has no IP
+#define IP_AP_NOTCOMPAT 10502 // IP and AP not compatible
+#define IP_END_NULLCOL 10503 // IP ends with anull column (normally not possible during compat. check)
+#define AP_TOO_SHORT 10504 // AP has been badly computed, leading to a AP shorter than needed (NB: it is an abnormal case)
+
+
 using namespace std;
 using namespace Qt;
 
diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp
index 7a4d4ff..e7239e0 100644
--- a/FunctionalBlock.cpp
+++ b/FunctionalBlock.cpp
@@ -28,8 +28,12 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference
   lengthOP = -1;
   lengthPP = -1;
   delta = -1;
+  evaluator = NULL;
 }
 
+FunctionalBlock::~FunctionalBlock() {
+  if (evaluator != NULL) delete evaluator;
+}
 
 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
   /*
@@ -115,26 +119,34 @@ QString FunctionalBlock::getReferenceHashMd5() {
     return ((ReferenceBlock *)reference)->getHashMd5();
 }
 
-bool FunctionalBlock::createPatterns() {
+void FunctionalBlock::createPatterns() throw(Exception) {
   static QString fctName = "FunctionalBlock::createPatterns()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
   
   cout << "create patterns for block " << qPrintable(name) << endl;
-  evaluator = new ArithmeticEvaluator();
+  if (evaluator == NULL) evaluator = new ArithmeticEvaluator();
   bool ok = true;  
   if (! isGeneratorBlock()) {
-    ok = ok & createDelta();
-    if (ok) ok = ok & createConsumptionPattern();    
-    if (ok) ok = ok & createProductionCounter();
+    try {
+      createDelta();
+      createConsumptionPattern();    
+      createProductionCounter();
+    }
+    catch(Exception e) {
+      throw(e); // rethrow e
+    }
   }
-  if (ok) ok = ok & createProductionPattern();
-  delete evaluator;
-  return ok;
+  try {
+    createProductionPattern();
+  }
+  catch(Exception e) {
+    throw(e);
+  }  
 }
 
-bool FunctionalBlock::createDelta() {
+void FunctionalBlock::createDelta() throw(Exception) {
   static QString fctName = "FunctionalBlock::createDelta()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -144,21 +156,23 @@ bool FunctionalBlock::createDelta() {
   cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;
   if (deltaStr.isEmpty()) {
     delta = -1;
-    return true;
+    return;
   }
   
   // look for parameter names
   bool ok = true;
-  double result = evaluateExpression(deltaStr, &ok);
-  if (!ok) return false;
-  
+  double result = 0;
+  try {
+    result = evaluateExpression(deltaStr);
+  }
+  catch(Exception e) {
+    throw(e);
+  }
   delta = result;
   cout << "delta = " << delta << endl;
-   
-  return true;
 }
 
-bool FunctionalBlock::createConsumptionPattern() {
+void FunctionalBlock::createConsumptionPattern()  throw(Exception) {
   static QString fctName = "FunctionalBlock::createConsumptionPattern()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -172,53 +186,63 @@ bool FunctionalBlock::createConsumptionPattern() {
     FunctionalInterface* connIface = AI_TO_FUN(iface);
     QString refName = connIface->getReference()->getName();    
     if (! consPattern.contains(refName)) {
+      throw(Exception(NO_IFACE_CP));
       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;
-      return false;
     }
-    QList<char>* pattern = expandPattern(consPattern.value(refName),&ok);        
-    if (!ok) return false;
+    QList<char>* pattern = NULL;
+    try {
+      pattern = expandPattern(consPattern.value(refName));
+    }
+    catch(Exception e) {
+      throw(e);
+    }
     consumptionPattern.insert(connIface,pattern);
     if (lengthCP == -1) {
       lengthCP = pattern->size();
     }
     else {
-      if (pattern->size() != lengthCP) return false;
+      if (pattern->size() != lengthCP) {
+        throw(Exception(INVALID_IFACE_CP_LENGTH));
+      }
     }
-  }        
-  return true;
+  }          
 }
 
-bool FunctionalBlock::createProductionPattern() {  
+void FunctionalBlock::createProductionPattern() throw(Exception){  
   static QString fctName = "FunctionalBlock::createProductionPattern()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
   
-  lengthPP = -1;
-  bool ok = true; 
+  lengthPP = -1;  
   QHash<QString,QString> prodPattern = implementation->getProductionPattern();  
   
   foreach(AbstractInterface* iface, getControlOutputs()) {    
     FunctionalInterface* connIface = AI_TO_FUN(iface);
     QString refName = connIface->getReference()->getName();    
     if (! prodPattern.contains(refName)) {
-      cerr << "no production pattern for reference interface " << qPrintable(refName) << endl;
-      return false;
+      throw(Exception(NO_IFACE_PP));      
+    }
+    QList<char>* pattern = NULL;
+    try {
+      pattern = expandPattern(prodPattern.value(refName));
+    }
+    catch(Exception e) {
+      throw(e);
     }
-    QList<char>* pattern = expandPattern(prodPattern.value(refName),&ok);
-    if (!ok) return false;
     productionPattern.insert(connIface,pattern);
     if (lengthPP == -1) {
       lengthPP = pattern->size();
     }
     else {
-      if (pattern->size() != lengthPP) return false;
+      if (pattern->size() != lengthPP) {
+        throw(Exception(INVALID_IFACE_PP_LENGTH));
+      }
     }
-  }    
-  return true;
+  }      
 }
 
-bool FunctionalBlock::createProductionCounter() {
+void FunctionalBlock::createProductionCounter() throw(Exception) {
   static QString fctName = "FunctionalBlock::createProductionCounter()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -236,14 +260,20 @@ bool FunctionalBlock::createProductionCounter() {
       s.remove(0,1);
       s.chop(1);
       QStringList gen = s.split(":");
-      if (gen.size() != 3) return false;
+      if (gen.size() != 3) {
+        throw(Exception(INVALID_IFACE_PC));
+      }
       int start = 0;
       int nb = 0;
       int step = 0;
-      for(int i=0;i<3;i++) {
-        bool okVal;
-        double result = evaluateExpression(gen.at(i),&okVal);
-        if (!okVal) return false;
+      for(int i=0;i<3;i++) {        
+        double result = 0.0;
+        try {
+          result = evaluateExpression(gen.at(i));
+        }
+        catch(Exception e) {
+          throw(e);
+        }
         if (i==0) start = result;
         else if (i==1) nb = result;
         else if (i==2) step = result;
@@ -252,11 +282,14 @@ bool FunctionalBlock::createProductionCounter() {
         productionCounter.append(start+j*step);
       }
     }
-    else {
-      bool okVal;
-      double result = evaluateExpression(s,&okVal);
-      
-      if (!okVal) return false;
+    else {      
+      double result = 0.0;
+      try {
+        result = evaluateExpression(s);
+      }
+      catch(Exception e) {
+        throw(e);
+      }
       productionCounter.append(result);      
     }
   }
@@ -264,11 +297,9 @@ bool FunctionalBlock::createProductionCounter() {
     cout << val << ",";
   }
   cout << endl;
-  
-  return true;
 }
 
-QList<char>* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok) {
+QList<char>* FunctionalBlock::expandPattern(const QString& patternIn) throw(Exception) {
   static QString fctName = "FunctionalBlock::expandPattern()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -277,22 +308,30 @@ QList<char>* FunctionalBlock::expandPattern(const QString& patternIn, bool* ok)
   QList<char> lst;
   QString  p = patternIn;
   p.append(')');
-  int offset = 0;
+  int offset = 0;  
   QList<char>* patternOut = new QList<char>();
-  expandPatternRecur(p,&offset,ok,patternOut);   
+  try {
+    expandPatternRecur(p,&offset, patternOut); 
+  }
+  catch(Exception e) {
+    throw(e);
+  }
+
   return patternOut;
 }
 
-void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, bool *ok, QList<char>* patternOut) {  
+void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset, QList<char>* patternOut) throw(Exception) {  
   
   while ((*offset < patternIn.size()) && (patternIn.at(*offset) != ')')) {
     
     QChar c = patternIn.at(*offset);
     if (c == '(') {
       *offset += 1;
-      expandPatternRecur(patternIn,offset, ok, patternOut);
-      if (!ok) {
-        return;
+      try {
+        expandPatternRecur(patternIn,offset, patternOut);
+      }
+      catch(Exception e) {
+        throw(e);
       }
     }
     else if (c == '0') {
@@ -312,13 +351,15 @@ void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset,
         *offset += 1;
       }
       if (*offset == patternIn.size()) {
-        *ok = false;
-        return;
+        throw(Exception(INVALID_IFACE_PATTERN));
+      }
+      double repeat = 0;
+      try {
+        repeat = evaluateExpression(expr);
+      }
+      catch(Exception e) {
+        throw(e);
       }
-      double repeat = evaluateExpression(expr,ok);
-      if (!ok) {
-        return;      
-      }            
       // repeat just the last value in currentGroup
       char last = patternOut->last();      
       //cout << "repeat last char " << repeat << " times : " << (int)last << endl;
@@ -339,12 +380,14 @@ void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset,
       *offset += 1;
     }
     if (*offset == patternIn.size()) {
-      *ok = false;
-      return;
+      throw(Exception(INVALID_IFACE_PATTERN));
     }
-    double repeat = evaluateExpression(expr,ok);
-    if (!ok) {
-      return;      
+    double repeat = 0;
+    try {
+      repeat = evaluateExpression(expr);
+    }
+    catch(Exception e) {
+      throw(e);
     }
     /*
     cout << "repeat last group " << repeat << " times : ";
@@ -355,18 +398,15 @@ void FunctionalBlock::expandPatternRecur(const QString& patternIn, int *offset,
     for(int i=1;i<(int)repeat;i++) {
       patternOut->append(single);
     }    
-  }
-  //*offset += 1;
-  return;
+  }  
 }
 
-double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok) {
+double FunctionalBlock::evaluateExpression(const QString& expression) throw(Exception) {
   static QString fctName = "FunctionalBlock::evaluateExpression()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
-  
-  *ok = true;
+    
   QHash<QString,double> vars;
   evaluator->setExpression(expression);
   QList<QString> varNames = evaluator->getVariableNames();
@@ -375,34 +415,29 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok)
     paramName.remove(0,1);
     BlockParameter* param = reference->getParameterFromName(paramName);    
     if (param == NULL) {
-      cerr << "found an unknown parameter in delta"<< endl;
-      *ok = false;
-      return 0.0;
+      throw(Exception(EVAL_PARAM_UNKNOWN));
     }
     bool okVal;
     int val = param->getDoubleValue(&okVal);
     if (!okVal) {
-      cerr << "cannot obtain double value of paramter " << qPrintable(paramName) << endl;
-      *ok = false;
-      return 0.0;
+      throw(Exception(EVAL_PARAM_NOVALUE));      
     }
     vars.insert(name,(double)val);    
   }
   
   evaluator->setVariablesValue(vars);
-  double result;
+  double result = 0.0;
   try {
     result = evaluator->evaluate();
   }
   catch(int index) {
     cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;
-    *ok = false;
-    return 0.0;
+    throw(Exception(EVAL_INVALID_EXPR));
   }
   return result;
 }
 
-void FunctionalBlock::createInputPattern() {
+void FunctionalBlock::createInputPattern()  throw(Exception) {
   static QString fctName = "FunctionalBlock::createInputPattern())";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -412,33 +447,32 @@ void FunctionalBlock::createInputPattern() {
   foreach(AbstractInterface* iface, getControlInputs()) {      
     ConnectedInterface* connIface = AI_TO_CON(iface);
     QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
+    if (out->size() == 0) {
+      clearInputPattern();
+      throw(Exception(NO_IFACE_IP));
+    }
     if (lengthIP == -1) {
       lengthIP = out->size();
     }
     else {
       if (out->size() < lengthIP) lengthIP = out->size();
     }
-    if (out->size() > 0) {
-      QList<char>* in = new QList<char>(*out);
-      foreach(char c, *in) {
-        cout << (int)c;
-      }
-      cout << endl;
-
-      inputPattern.insert(connIface,in);
+    
+    QList<char>* in = new QList<char>(*out);
+    foreach(char c, *in) {
+      cout << (int)c;
     }
-    else {
-      inputPattern.insert(connIface,NULL);
-    }      
+    cout << endl;    
+    inputPattern.insert(connIface,in);    
   }
-  // remove null columns at the end of IP
+  // search the last valid group in IP,
   while(! isValidDataGroup(inputPattern,lengthIP-1)) {
-    removeDataGroup(inputPattern,lengthIP-1);
+    //removeDataGroup(inputPattern,lengthIP-1);
     lengthIP -= 1;
   }
 }
 
-bool FunctionalBlock::createAdmittance(int nbExec) {
+void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) {
   static QString fctName = "FunctionalBlock::createAdmittance()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -497,8 +531,7 @@ bool FunctionalBlock::createAdmittance(int nbExec) {
         j -= 1;
       }
       else {
-        cout << "AP and CP are not consistent" << endl;
-        return false;
+        throw(INVALID_DELTA_CP);        
       }
     }
   }
@@ -512,11 +545,10 @@ bool FunctionalBlock::createAdmittance(int nbExec) {
       cout << (int)(pattern->at(i));
     }
     cout << endl;
-  }
-  return true;
+  }  
 }
 
-bool FunctionalBlock::checkInputPatternCompatibility() {
+void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) {
   static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -524,20 +556,21 @@ bool FunctionalBlock::checkInputPatternCompatibility() {
   
   bool ok = true;
   // firstly, create input pattern
-  createInputPattern();      
-  // if some patterns are not available, end now, returning false
-  if (lengthIP == 0) {
-    clearInputPattern();
-    return false;
+  try {
+    createInputPattern();
+  }
+  catch(Exception e) {
+    throw(e);
   }
-  int nbExec = getNumberOfExecution();
+  int nbExec = createTriggers();
   cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;
   
-  ok = createAdmittance(nbExec);
-  
-  if (!ok) {
+  try {
+    createAdmittance(nbExec);
+  }
+  catch(Exception e) {
     cout << "cannot create admittance" << endl;
-    return false;
+    throw(e);
   }
   
   int clock = 0; // index in IP  
@@ -549,7 +582,7 @@ bool FunctionalBlock::checkInputPatternCompatibility() {
       while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;
       if (clock == lengthIP) {
         cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;
-        return false;
+        throw(Exception(IP_END_NULLCOL));        
       }
     }    
     /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or
@@ -557,19 +590,18 @@ bool FunctionalBlock::checkInputPatternCompatibility() {
     */
     if (! samePatterns(inputPattern,clock,admittance,i)) {
       cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;
-      return false;
+      throw(Exception(IP_AP_NOTCOMPAT)); // IP and AP not compatible
     }
     clock++;
     i++;
   }
   if (clock < lengthIP) {
-    cerr << "Abnormal case: AP is to short" << endl;
-    return false;
-  }
-  return true;
+    throw(Exception(AP_TOO_SHORT));
+    cerr << "Abnormal case: AP is to short" << endl;   
+  }  
 }
 
-bool FunctionalBlock::computeOutputPattern(int nbExec) {
+void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {
   static QString fctName = "FunctionalBlock::computeOutputPattern()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -600,11 +632,11 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
     // in case of inputPattern not created, do it
     if (lengthIP <= 0) {
       // collect the input patterns for each input    
-      createInputPattern();    
-      // if some patterns are not available, end now, returning false
-      if (lengthIP == 0) {
-        clearInputPattern();
-        return false;
+      try {
+        createInputPattern();
+      }
+      catch(Exception e) {
+        throw(e);
       }
       cout << "input pattern array initialized with min. len " << lengthIP << endl;
     }
@@ -692,8 +724,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
 
     // clear input pattern
     clearInputPattern();
-  }
-  return true;
+  }  
 }
 
 bool FunctionalBlock::samePatterns(const QMap<AbstractInterface*, QList<char>* >& patternSrc, int srcCol, const QMap<AbstractInterface*, QList<char>* >& patternDest, int destCol) {
@@ -842,24 +873,24 @@ void FunctionalBlock::clearInputPattern() {
   lengthIP = -1;
 }
 
-int FunctionalBlock::getNumberOfExecution() {
+int FunctionalBlock::createTriggers() {
+  triggers.clear();
   /* NB: this method returns the number of executions that have been started
      but not necessary completed.
   */
-  if (delta <= 0) return 0;
-  int nbExec = 0;
+  if (delta <= 0) return 0;  
   int offset = 0;
   // search for the first exec.
   while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;
   if (offset == lengthIP) return 0;
-  nbExec = 1;
+  triggers.append(offset);  
   int nbGroup = 0;
   for(int i = offset;i<lengthIP;i++) {
     if (isValidDataGroup(inputPattern,i)) nbGroup++;
     if (nbGroup == delta+1) {
-      nbExec += 1;
+      triggers.append(i);
       nbGroup = 1;
     }
   }      
-  return nbExec;  
+  return triggers.size();
 }
diff --git a/FunctionalBlock.h b/FunctionalBlock.h
index f27bef6..440c154 100644
--- a/FunctionalBlock.h
+++ b/FunctionalBlock.h
@@ -27,7 +27,7 @@ class FunctionalBlock : public AbstractBlock {
 public:
 
   FunctionalBlock(GroupBlock* _parent, ReferenceBlock* _reference) throw(Exception);
-
+  ~FunctionalBlock();
   // getters
   inline ReferenceBlock* getReference() { return reference; }
   inline QList<int> getProductionCounter() { return productionCounter; }
@@ -56,26 +56,26 @@ public:
   QString getReferenceHashMd5();
   
   // patterns
-  bool createPatterns(); // called in Graph, before checking compatibility and computing output pattern
-  bool checkInputPatternCompatibility();
-  bool computeOutputPattern(int nbExec = -1);
+  void createPatterns() throw(Exception); // called in Graph, before checking compatibility and computing output pattern
+  void checkInputPatternCompatibility() throw(Exception);
+  void computeOutputPattern(int nbExec = -1) throw(Exception);
   
 private:  
   // patterns
-  bool createDelta();
-  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
-  bool createAdmittance(int nbExec); // initialize a QList<char> from consumption pattern and delta
+  void createDelta() throw(Exception);
+  void createConsumptionPattern() throw(Exception); // initialize a QList<char> for each interface from patterns defined in implementation
+  void createProductionPattern() throw(Exception); // initialize a QList<char> for each interface from patterns defined in implementation
+  void createProductionCounter() throw(Exception); // initialize a QList<int> from counter defined in implementation
+  void createAdmittance(int nbExec) throw(Exception); // initialize a QList<char> from consumption pattern and delta
   void clearConsumptionPattern();
   void clearProductionPattern();
-  void createInputPattern();
+  void createInputPattern() throw(Exception);
   void clearInputPattern();
-  int getNumberOfExecution(); // compute number of block execution from inputPattern and delta
+  int createTriggers(); // compute the clock cycle at which the block is triggered
   
-  double evaluateExpression(const QString& expression, bool* ok);
-  QList<char>* expandPattern(const QString& patternIn, bool* ok);
-  void expandPatternRecur(const QString& patternIn, int* offset, bool* ok, QList<char> *patternOut);
+  double evaluateExpression(const QString& expression) throw(Exception);
+  QList<char>* expandPattern(const QString& patternIn) throw(Exception);
+  void expandPatternRecur(const QString& patternIn, int* offset, QList<char> *patternOut)  throw(Exception);
   /*!
    * \brief samePatterns
    * \param patternSrc the pattern that must be tested with patternDest (is patternDest == patternDest)  
@@ -151,7 +151,8 @@ private:
   QMap<AbstractInterface*, QList<char>* > productionPattern;
   QMap<AbstractInterface*,QList<char>* > inputPattern;
   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
+  QList<int> productionCounter; // only usefull for control output interfaces
+  QList<int> triggers; // the clock cycles at which the block is triggered, taking into account IP
   int lengthIP; // for convenience, set in createInputPattern()
   int lengthCP; // for convenience, set in createConsumptionPattern()
   int lengthAP; // for convenience, set in createAdmittance()
diff --git a/Graph.cpp b/Graph.cpp
index eb66dc4..0fb4fcb 100644
--- a/Graph.cpp
+++ b/Graph.cpp
@@ -2,6 +2,7 @@
 #include "GroupBlock.h"
 #include "ReferenceBlock.h"
 #include "FunctionalBlock.h"
+#include "Exception.h"
 
 Graph::Graph() {
   topGroup = new GroupBlock(NULL);
@@ -108,12 +109,16 @@ bool Graph::removeSourceBlock(FunctionalBlock *block) {
   return true;
 }
 
-bool Graph::createPatterns() {
+void Graph::createPatterns() throw(Exception) {
   bool ok = true;
   foreach(AbstractBlock* block, sources) {
     FunctionalBlock* funBlock = AB_TO_FUN(block);
-    ok = funBlock->createPatterns();
-    if (!ok) return false;
+    try {
+      funBlock->createPatterns();
+    }
+    catch(Exception e) {
+      throw(e);      
+    }
   }
   
   foreach(AbstractBlock* block, groups) {
@@ -121,12 +126,15 @@ bool Graph::createPatterns() {
     foreach(AbstractBlock* inBlock, group->getBlocks()) {
       if (inBlock->isFunctionalBlock()) {
         FunctionalBlock* funBlock = AB_TO_FUN(inBlock);
-        ok = funBlock->createPatterns();
-        if (!ok) return false;
+        try {
+          funBlock->createPatterns();
+        }
+        catch(Exception e) {
+          throw(e);
+        }
       }
     }
-  }
-  return true;
+  }  
 }
 
 void Graph::resetPatternComputed() {
@@ -144,7 +152,14 @@ void Graph::resetPatternComputed() {
 
 bool Graph::computeOutputPatterns(int nbExec) {
   
-  createPatterns();
+  try {
+    createPatterns();
+  }
+  catch(Exception e) {
+    cerr << qPrintable(e.getMessage()) << endl;
+    return false;
+  }
+
   resetPatternComputed();  
   // search for all block that are generators.
   QList<FunctionalBlock*> generators;
@@ -170,5 +185,11 @@ bool Graph::computeOutputPatterns(int nbExec) {
     block->computeOutputPattern((maxExecLen+d-1)/d);
   }
   // compute output for top group
-  topGroup->computeOutputPattern();
+  try {
+    topGroup->computeOutputPattern();
+  }
+  catch(Exception e) {
+    cerr << qPrintable(e.getMessage()) << endl;
+    return false;
+  }
 }
diff --git a/Graph.h b/Graph.h
index f3e9923..03d1882 100644
--- a/Graph.h
+++ b/Graph.h
@@ -10,7 +10,7 @@ class GroupBlock;
 class ReferenceBlock;
 class FunctionalBlock;
 class AbstractInterface;
-
+class Exception;
 using namespace std;
 using namespace Qt;
 
@@ -45,12 +45,12 @@ public:
   // others
   QList<AbstractInterface *> getOutsideInterfaces();
   /*!
-   * \brief initPatterns
-   * initPatterns() crosses the graph and for each functional block, it computes
+   * \brief createPatterns
+   * createPatterns() 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 createPatterns() throw(Exception);
   void resetPatternComputed();
   bool computeOutputPatterns(int nbExec);
   
diff --git a/GroupBlock.cpp b/GroupBlock.cpp
index 1b307da..b6fc702 100644
--- a/GroupBlock.cpp
+++ b/GroupBlock.cpp
@@ -113,12 +113,10 @@ void GroupBlock::createInputPattern() {
   }  
 }
 
-bool GroupBlock::checkInputPatternCompatibility() {
-  return true;
- 
+void GroupBlock::checkInputPatternCompatibility() throw(Exception){  
 }
 
-bool GroupBlock::computeOutputPattern(int nbExec) {
+void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) {
 
   static QString fctName = "GroupBlock::computeOutputPattern()";
 #ifdef DEBUG_FCTNAME
@@ -166,16 +164,23 @@ bool GroupBlock::computeOutputPattern(int nbExec) {
     
     if (block->getPatternComputed()) continue; // block has already been processed
     
-    compatible = block->checkInputPatternCompatibility();
-    if (!compatible) {
+    try {
+      block->checkInputPatternCompatibility();
+    }
+    catch(Exception e) {
       cout << qPrintable(block->getName()) << " is not compatible with his input pattern" << endl;
-      break;
+      throw(e);
+    }
+    compatible = true;
+    
+    try {
+      block->computeOutputPattern();
     }
-    canCompute = block->computeOutputPattern();
-    if (!canCompute) {
+    catch(Exception e) {    
       cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
-      break;
+      throw(e);      
     }
+    canCompute = true;
     block->setPatternComputed(true);
     // add other blocks connected from block to the fifo
     foreach(AbstractInterface* iface, block->getControlOutputs()) {
@@ -201,6 +206,5 @@ bool GroupBlock::computeOutputPattern(int nbExec) {
       connIface->setOutputPattern(pattern);    
     }
     setPatternComputed(true);
-  }
-  return canCompute;
+  }  
 }
diff --git a/GroupBlock.h b/GroupBlock.h
index 27e43cc..b3aaeaf 100644
--- a/GroupBlock.h
+++ b/GroupBlock.h
@@ -42,8 +42,8 @@ public:
   // public attributes
   static int counter;
 
-  bool checkInputPatternCompatibility();
-  bool computeOutputPattern(int nbExec = -1);
+  void checkInputPatternCompatibility() throw(Exception);
+  void computeOutputPattern(int nbExec = -1) throw(Exception);
   
 private:    
   // patterns  
diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp
index 89bde3a..a31db67 100644
--- a/ReferenceBlock.cpp
+++ b/ReferenceBlock.cpp
@@ -567,11 +567,11 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
   return in;
 }
 
-bool ReferenceBlock::checkInputPatternCompatibility() {
-  return false;
+void ReferenceBlock::checkInputPatternCompatibility()  throw(Exception){
+  throw(Exception(INVALID_REFBLOCK_USE));
 }
 
-bool ReferenceBlock::computeOutputPattern(int nbExec) {
+void ReferenceBlock::computeOutputPattern(int nbExec)  throw(Exception) {
   // does strictly nothing
-  return false;
+  throw(Exception(INVALID_REFBLOCK_USE));  
 }
diff --git a/ReferenceBlock.h b/ReferenceBlock.h
index 8212fcd..b1ebd84 100644
--- a/ReferenceBlock.h
+++ b/ReferenceBlock.h
@@ -68,8 +68,8 @@ public:
   
 private:
   // patterns
-  bool checkInputPatternCompatibility();
-  bool computeOutputPattern(int nbExec = -1);
+  void checkInputPatternCompatibility() throw(Exception);
+  void computeOutputPattern(int nbExec = -1) throw(Exception);
 };
 
 #endif // __REFERENCEBLOCK_H__
diff --git a/blast.creator.user b/blast.creator.user
index fa27125..aea89f7 100755
--- a/blast.creator.user
+++ b/blast.creator.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 3.2.1, 2017-05-22T11:04:55. -->
+<!-- Written by QtCreator 3.2.1, 2017-05-22T16:26:54. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>