From: stephane Domas <stephane.domas@univ-fcomte.fr>
Date: Tue, 15 May 2018 17:43:56 +0000 (+0200)
Subject: finished testbench generation
X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain/e0eaffd44fc9733bc230a803c80d8d5efd0faca6?hp=bc5d59217a24b25c1b913bec4a41dd026d02720c

finished testbench generation
---

diff --git a/AbstractBlock.cpp b/AbstractBlock.cpp
index 218ea61..de28272 100644
--- a/AbstractBlock.cpp
+++ b/AbstractBlock.cpp
@@ -76,8 +76,10 @@ bool AbstractBlock::isStimuliBlock() {
  * and has at least one data output.
  * By the way, blocks that have no data input/output
  * (like clkrstgen) are not sources !
+ * A source may also be a block of special type source.
  */
 bool AbstractBlock::isSourceBlock() {
+  if (specialType == Source) return true;
   if (getDataInputs().size() > 0) return false;
   if (getDataOutputs().size() == 0) return false;
   return true;
diff --git a/AbstractBlock.h b/AbstractBlock.h
index efbd474..f40af86 100644
--- a/AbstractBlock.h
+++ b/AbstractBlock.h
@@ -75,7 +75,7 @@ public:
   virtual bool isGroupBlock();
   virtual bool isStimuliBlock(); //! a stimuli block is outside the top group and simulates a peripheral (NB: this is also a source)
   virtual bool isTopGroupBlock();
-  bool isSourceBlock(); //! a source block has no data inputs and thus executes infinitely
+  bool isSourceBlock(); //! a source block is either a block that has no data inputs or that is of special type source. Thus it executes infinitely
   bool isSinkBlock(); //! a sink block has no data outputs and just collects what it receives (i.e. no compatibility check)
   bool isWBConfigurable();
 
diff --git a/AbstractInterface.cpp b/AbstractInterface.cpp
index 3fdd87a..83aa4c3 100644
--- a/AbstractInterface.cpp
+++ b/AbstractInterface.cpp
@@ -14,8 +14,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
   type = Boolean;
   endianess = LittleEndian;
   associatedIface = NULL;
-  clkIface = "";
-  clkIfaceType = 0;
+  clkIfaceName = "";
+  clkIfaceType = NoName;
 
 }
 
@@ -29,8 +29,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name
   type = typeFromString(_type);
   endianess = _endianess;
   associatedIface = NULL;
-  clkIface = "";
-  clkIfaceType = 0;
+  clkIfaceName = "";
+  clkIfaceType = NoName;
 }
 
 AbstractInterface::AbstractInterface(AbstractInterface* other) {
@@ -42,7 +42,7 @@ AbstractInterface::AbstractInterface(AbstractInterface* other) {
   purpose = other->purpose;
   endianess = LittleEndian;
   associatedIface = NULL;
-  clkIface = other->clkIface;
+  clkIfaceName = other->clkIfaceName;
   clkIfaceType = other->clkIfaceType;
 }
 
@@ -216,7 +216,7 @@ bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) {
 
 AbstractInterface* AbstractInterface::getClockIface() {
   if (clkIfaceType == ClockName) {
-    return owner->getIfaceFromName(clkIface);
+    return owner->getIfaceFromName(clkIfaceName);
   }
   return NULL;
 }
@@ -227,7 +227,7 @@ double AbstractInterface::getClockFrequency() throw(Exception) {
   int idClock = -1;
 
   if (clkIfaceType == ParameterName) {
-    BlockParameter* param = owner->getParameterFromName(clkIface);
+    BlockParameter* param = owner->getParameterFromName(clkIfaceName);
     if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
     bool ok;
     double freq = param->getDoubleValue(&ok);
@@ -247,46 +247,6 @@ double AbstractInterface::getClockFrequency() throw(Exception) {
 }
 
 
-bool AbstractInterface::setClockIface(QString name) {
-  /* 2 cases :
-   *  - this is a Data interface
-   *  - this is a Clock output (from a clkrstgen)
-   *
-   *   iface must correspond to an existing clock interface name
-   * or a user parameter prepend with a $.
-   */
-  if ((purpose == Data) || ((purpose == Clock) && (direction == Output))) {
-    if (name.at(0) == '$') {
-      name.remove(0,1);
-      QList<BlockParameter* > params = owner->getUserParameters();
-      foreach(BlockParameter* p, params) {
-        if (p->getName() == name) {
-          clkIface = name;
-          clkIfaceType = ParameterName;
-          return true;
-        }
-      }
-      // error case: cannot found the input clock
-      return false;
-    }
-    else {
-      QList<AbstractInterface*> clocks = owner->getInterfaces(Input, Clock);
-      foreach(AbstractInterface* iface, clocks) {
-        if (iface->getName() == name) {
-          clkIface = name;
-          clkIfaceType = ClockName;
-          return true;
-        }
-      }
-      // error case: cannot found the user paramter
-      return false;
-    }
-  }
-  clkIface = "";
-  clkIfaceType = NoName;
-  return true;
-}
-
 
 int AbstractInterface::getIntDirection(QString str) {
     if(str == "input") return Input;
@@ -351,7 +311,10 @@ QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exc
   //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
 
   if (context == Instance) {
-    if (direction == Output) {
+    if (direction == Input) {
+      ret = owner->getName()+"_"+name;
+    }
+    else if (direction == Output) {
       ret = "from_"+owner->getName()+"_"+name;
     }
     else if (direction == InOut) {
diff --git a/AbstractInterface.h b/AbstractInterface.h
index 832fe48..0ad387a 100644
--- a/AbstractInterface.h
+++ b/AbstractInterface.h
@@ -30,7 +30,7 @@ public :
   enum IfaceDirection { AnyDirection = 0, Input = 1, Output = 2, InOut = 3 };  
   enum IfaceVHDLContext {AnyContext = 0, Entity = 1, Component = 2, Instance = 3, Signal = 4 };
   enum IfaceVHDLFlags { NoComma = 1 };
-  enum IfaceClockName { NoName = 0, ClockName, ParameterName };
+  enum IfaceClockName { NoName = 0, ClockName, ParameterName, InheritedName };
 
   static int getIntDirection(QString str);
   static int getIntPurpose(QString str);
@@ -54,7 +54,7 @@ public :
   QString getDirectionString();  
   inline AbstractBlock *getOwner() { return owner;}
   inline AbstractInterface* getAssociatedIface() { return associatedIface; }
-  inline QString getClockIfaceString() { return clkIface; }
+  inline QString getClockIfaceString() { return clkIfaceName; }
   inline int getClockIfaceType() { return clkIfaceType; }
   AbstractInterface* getClockIface();
   virtual int getClockDomain() throw(Exception) = 0; // determine on which clock domain is sync this interface
@@ -71,7 +71,8 @@ public :
   void setPurpose(int _purpose);
   void setDirection(int _direction);
   bool setAssociatedIface(AbstractInterface* iface);
-  bool setClockIface(QString name);
+  inline void setClockIfaceType(int type) { clkIfaceType = type; }
+  inline void setClockIfaceName(QString name) { clkIfaceName = name; }
   
   // testers
   virtual bool isReferenceInterface();
@@ -112,7 +113,7 @@ protected:
    * Nevertheless, the designer has the possibility to connect the block taht owns this interface to another clkrstgen block.  Moreover,
    * some blocks may have several clocks, e.g. dual port RAMs, FIFOs.
    */
-  QString clkIface;
+  QString clkIfaceName;
   int clkIfaceType; // 0 for not affected, 1 for clock input name, 2 for user param name
   
   
diff --git a/BlockParameterGeneric.cpp b/BlockParameterGeneric.cpp
index 14b8c59..4ba6c8e 100644
--- a/BlockParameterGeneric.cpp
+++ b/BlockParameterGeneric.cpp
@@ -75,6 +75,20 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) {
         ret = formatNoValue.arg(name).arg(typeStr);
       }
     }
+    else if (type == String) {
+      typeStr = "string";
+      if (!userValue.isNull()) {
+        valueStr = "\""+userValue.toString()+"\"";
+        ret = formatValue.arg(name).arg(typeStr).arg(valueStr);
+      }
+      else if (!defaultValue.isNull()) {
+        valueStr = "\""+defaultValue.toString()+"\"";
+        ret = formatValue.arg(name).arg(typeStr).arg(valueStr);
+      }
+      else {
+        ret = formatNoValue.arg(name).arg(typeStr);
+      }
+    }
     else {
       typeStr = getTypeString();
       if (!userValue.isNull()) {
@@ -109,6 +123,9 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) {
         if ((type == Boolean)||(type == Bit)) {
           ret = format.arg(name).arg("'"+userValue.toString()+"'");
         }
+        else if (type == String) {
+          ret = format.arg(name).arg("\""+userValue.toString()+"\"");
+        }
         else {
           ret = format.arg(name).arg(userValue.toString());
         }
@@ -117,6 +134,9 @@ QString BlockParameterGeneric::toVHDL(int context, int flags) {
         if ((type == Boolean)||(type == Bit)) {
           ret = format.arg(name).arg("'"+defaultValue.toString()+"'");
         }
+        else if (type == String) {
+          ret = format.arg(name).arg("\""+defaultValue.toString()+"\"");
+        }
         else {
           ret = format.arg(name).arg(defaultValue.toString());
         }
diff --git a/ConnectedInterface.h b/ConnectedInterface.h
index c9e03e8..e3dbfd3 100644
--- a/ConnectedInterface.h
+++ b/ConnectedInterface.h
@@ -42,8 +42,8 @@ public :
   inline bool isConnectedTo(){return connectedTo.length() != 0;}
   inline bool isConnectedToMany(){return connectedTo.length()>=2;}
   inline bool isConnectedFrom(){return connectedFrom != NULL;}
-  virtual bool canConnectTo(AbstractInterface* iface) = 0;
-  virtual bool canConnectFrom(AbstractInterface* iface) = 0;
+  virtual bool canConnectTo(AbstractInterface* iface, bool testClock) = 0;
+  virtual bool canConnectFrom(AbstractInterface* iface, bool testClock) = 0;
 
   // others  
   void resetOutputPattern() { outputPattern = NULL; }
diff --git a/DelayInputModifier.cpp b/DelayInputModifier.cpp
index db89107..242547c 100644
--- a/DelayInputModifier.cpp
+++ b/DelayInputModifier.cpp
@@ -34,11 +34,12 @@ QString DelayInputModifier::toVHDL(int context, int flags) throw(Exception) {
   dm2.setNum(delayLength-2);
   dm3.setNum(delayLength-3);
   QString ret="";
-  QString clkName = "clk";
-  QString resetName = "reset";
+  int idClock = toIface->getClockDomain();
+  QString clkName = "ext_clk_"+QString::number(idClock);
+  QString resetName = "ext_reset_"+QString::number(idClock);
   if (toIface->getOwner()->getParent()->isTopGroupBlock()) {
-    clkName = "from_clkrstgen_clk";
-    resetName ="from_clkrstgen_reset";
+    clkName = "from_clkrstgen_"+QString::number(idClock)+"_clk";
+    resetName ="from_clkrstgen_"+QString::number(idClock)+"_reset";
   }
 
   if (context == Architecture) {
diff --git a/Dispatcher.cpp b/Dispatcher.cpp
index 266160b..574243e 100644
--- a/Dispatcher.cpp
+++ b/Dispatcher.cpp
@@ -100,7 +100,16 @@ void Dispatcher::setSceneCounter(Context context, int value) {
 }
 
 bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
-    
+  static QString fctName = "Dispatcher::createConnection()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  bool testClock = false;
+  if (context == Design) {
+    testClock = true;
+  }
+
   ConnectedInterface* ref1 = iface1->refInter;
   ConnectedInterface* ref2 = iface2->refInter;  
   // connect both interface
@@ -108,30 +117,33 @@ bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, Interf
   bool ok1 = false;
   bool ok2 = false;
 
+  cout << "trying to create a connection between " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
+  cout << " and " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
+
   // test the ref1->ref2 connection
-  if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
+  if ((ref1->canConnectTo(ref2,testClock)) && (ref2->canConnectFrom(ref1,testClock))) {
     ref1->connectTo(ref2);    
     ok1 = true;
   }
   // if the first one did not work, test ref2->ref1
-  if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {  
+  if ((ok1 == false) && (ref2->canConnectTo(ref1,testClock)) && (ref1->canConnectFrom(ref2,testClock))) {
     ref2->connectTo(ref1);    
     ok2 = true;
   }
   if ((ok1 == true) || (ok2 == true)) {    
 
     if (ok1) {
-      cout << "trying to create a connection from " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
+      cout << " ... done with " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
       cout << " to " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
       iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
     }
     else {
-      cout << "trying to create a connection from " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
+      cout << "... done with " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
       cout << " to " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
       iface2->getOwner()->getScene()->createConnectionItem(iface2,iface1, visible);
     }
 
-    cout << " ... done." << endl;
+    cout << endl;
 
     unselectAllItems(context);
     params->unsaveModif = true;    
@@ -200,6 +212,12 @@ void Dispatcher::generateVHDL(Context context) throw(Exception) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   QDir baseDir(params->projectPath);
   QDir srcDir(params->projectPath+"/src");
@@ -304,6 +322,12 @@ void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   if (item->getRefBlock()->isFunctionalBlock()) {
     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
@@ -321,6 +345,12 @@ void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
     
   GroupWidget* win = item->getScene()->getGroupWidget();
   
@@ -360,6 +390,12 @@ void Dispatcher::renameGroupBlock(Context context, GroupItem *item){
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   
   GroupWidget* win = item->getScene()->getGroupWidget();
   
@@ -406,6 +442,12 @@ void Dispatcher::renameStimuliItem(Context context, StimuliItem *item){
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
     
   GroupWidget* win = item->getScene()->getGroupWidget();
   
@@ -446,6 +488,11 @@ void Dispatcher::renameInterface(Context context, InterfaceItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
   
@@ -490,6 +537,12 @@ void Dispatcher::showPatterns(Context context, InterfaceItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   QString msg = "";
   if (item->refInter->getDirection() == AbstractInterface::Input) {
     msg = "Input pattern of iface ";
@@ -534,6 +587,12 @@ void Dispatcher::showModifier(Context context, InterfaceItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   QString msg = "";
   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
   AbstractInputModifier* mod = assoIface->getInputModifier();
@@ -551,10 +610,16 @@ void Dispatcher::showModifier(Context context, InterfaceItem *item) {
 }
 
 void Dispatcher::removeModifier(Context context, InterfaceItem *item) {
-  static QString fctName = "Dispatcher::showModifier()";
+  static QString fctName = "Dispatcher::removeModifier()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
   assoIface->clearInputModifier();
@@ -566,6 +631,12 @@ void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   GroupScene *scene = item->getScene();
   AbstractBlock* block = item->getRefBlock();  
@@ -589,6 +660,12 @@ void Dispatcher::duplicateStimuliItem(Context context, StimuliItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   GroupScene *scene = item->getScene();
   AbstractBlock* block = item->getRefBlock();  
@@ -612,6 +689,12 @@ void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
 
   AbstractInterface *refI = item->refInter;
   if (! refI->isFunctionalInterface()) return;
@@ -1106,8 +1189,11 @@ void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
-
-  if (context != Design) return;
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   /* a BoxItem (group of func) can be removed only if none of its
      interfaces is connected to a group interface that is itself
@@ -1182,6 +1268,11 @@ void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *ite
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
     foreach(ConnectionItem* conn, ifaceItem->connections) {
@@ -1195,6 +1286,11 @@ void Dispatcher::removeStimuliItem(Context context, StimuliItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
   
   QString msg = "Removing stimmuli ";
   
@@ -1218,6 +1314,12 @@ void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
   InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
 
@@ -1291,6 +1393,16 @@ void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
 
 void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clkName, int idGen) throw(Exception) {
 
+  static QString fctName = "Dispatcher::connectBoxItemClock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   InterfaceItem* fromIfaceItemClk = NULL;
   InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName);
   GroupItem* parentGroup = item->getScene()->getGroupItem();
@@ -1324,6 +1436,17 @@ void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clk
 }
 
 void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rstName, int idGen) throw(Exception) {
+
+  static QString fctName = "Dispatcher::connectBoxItemReset()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   InterfaceItem* fromIfaceItemRst = NULL;
   InterfaceItem* toIfaceItemRst = item->searchInterfaceItemByName(rstName);
   GroupItem* parentGroup = item->getScene()->getGroupItem();
@@ -1357,6 +1480,17 @@ void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rst
 }
 
 void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QString clkName, int idGen) throw(Exception) {
+
+  static QString fctName = "Dispatcher::connectStimuliItemClock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   InterfaceItem* fromIfaceItemClk = NULL;
   InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName);
   BoxItem* clkrstItem = NULL;
@@ -1381,6 +1515,16 @@ void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QSt
 }
 
 void Dispatcher::connectStimuliItemReset(Context context, StimuliItem *item, QString rstName, int idGen) throw(Exception) {
+  static QString fctName = "Dispatcher::connectStimuliItemReset()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   InterfaceItem* fromIfaceItemRst = NULL;
   InterfaceItem* toIfaceItemRst = item->searchInterfaceItemByName(rstName);
   BoxItem* clkrstItem = NULL;
@@ -1412,6 +1556,17 @@ void Dispatcher::showBlocksLibrary(){
 }
 
 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
+
+  static QString fctName = "Dispatcher::showProperties()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   QDialog* dial = new InterfacePropertiesDialog(inter);
   dial->exec();
 }
@@ -1424,6 +1579,16 @@ void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
 */
 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
 
+  static QString fctName = "Dispatcher::connectInterToGroup()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
+
   // getting the GroupBlock and GroupItem that are parent of the block that owns item
   ConnectedInterface *refInter = item->refInter;
   cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
@@ -1445,7 +1610,12 @@ void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
   parentItem->addInterfaceItem(groupIfaceItem,true);
 
   // creating the connection, in graph and with an item
-  createConnection(context, item, groupIfaceItem);
+  /* NOTE:
+     Since the group interface is for now unconnected, it is impossible to determine
+     its clock domain. Thus, the connection must be created without testing the clock domain
+     consistency. For that, we cheat by changing the context to Load because it implies no clock test.
+   */
+  createConnection(Load, item, groupIfaceItem);
 
   // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
   BoxItem* parent2Item = parentItem->getParentItem();
@@ -1465,6 +1635,11 @@ void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item)
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   /* first, remove all connections from item
      NB:  if there is a connection to a group interface, then this
@@ -1488,6 +1663,11 @@ void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   /* NB: just remove all connections from/to this item, since when there are no more
      ones to a GroupItem, it is automatically deleted.
@@ -1566,6 +1746,11 @@ void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block)
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
+  /* NB: only called in Design context */
+  if (context != Design) {
+    cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
+    return;
+  }
 
   block->computeAdmittanceDelays();
   // get the block item that is associated to block
diff --git a/FunctionalBlock.cpp b/FunctionalBlock.cpp
index 89250ec..98e5e87 100644
--- a/FunctionalBlock.cpp
+++ b/FunctionalBlock.cpp
@@ -1422,12 +1422,19 @@ void FunctionalBlock::generateComments(QTextStream& out, QDomElement &elt, QStri
     QDomElement eltModif = nodeModif.toElement();
   }
   out << "-- Description   : " << endl;
-  out << reference->getDescription() << endl;
+  QStringList lines = reference->getDescription().split("\n");
+  foreach(QString line, lines) {
+    out << "--   " << line << endl;
+  }
   out << "--" << endl;
   QDomElement eltNote = eltLog.nextSiblingElement("notes");
   QDomElement note = eltNote.firstChildElement();
   QString noteTxt = note.text();
-  out << "--  Notes          :\n"<<noteTxt<<endl;
+  out << "--  Notes          :" << endl;
+  lines = noteTxt.split("\n");
+  foreach(QString line, lines) {
+    out << "--   " << line << endl;
+  }
   out << "--" << endl;
   for(int i = 0; i < 50; i++) {
     out << "--";
diff --git a/FunctionalBlock.h b/FunctionalBlock.h
index e3b8167..93ac7d1 100644
--- a/FunctionalBlock.h
+++ b/FunctionalBlock.h
@@ -46,7 +46,7 @@ public:
 
   // testers
   bool isFunctionalBlock();
-  bool isStimuliBlock(); //! a stimuli block has no parent and has no data inputs
+  bool isStimuliBlock(); //! a stimuli block has no parent and is out of the top group
 
   // others
 
diff --git a/FunctionalInterface.cpp b/FunctionalInterface.cpp
index 55f65ec..3a225c7 100644
--- a/FunctionalInterface.cpp
+++ b/FunctionalInterface.cpp
@@ -21,7 +21,9 @@ FunctionalInterface::FunctionalInterface(AbstractBlock* _owner, ReferenceInterfa
   width = reference->getWidthString();
   direction = reference->getDirection();
   purpose = reference->getPurpose();  
-  connectedFrom = NULL;  
+  connectedFrom = NULL;
+  clkIfaceName = reference->getClockIfaceString();
+  clkIfaceType = reference->getClockIfaceType();
 }
 
 bool FunctionalInterface::isFunctionalInterface() {
@@ -82,7 +84,12 @@ AbstractInterface *FunctionalInterface::clone() {
   return inter;
 }
 
-bool FunctionalInterface::canConnectTo(AbstractInterface *iface) {
+bool FunctionalInterface::canConnectTo(AbstractInterface *iface, bool testClock) {
+  static QString fctName = "FunctionalInterface::canConnectTo()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
 
   /* NOTE :
      necessary conditions :
@@ -99,14 +106,19 @@ bool FunctionalInterface::canConnectTo(AbstractInterface *iface) {
         2.2 - both are inout
      3 - this is owned by a source block and iface is owned by the top group
 
+     + if testClock is true, must test if both ifaces are in the same clock domain. Note that a group interface
+     has always
      special case : clk/reset from clkrstgen can connect to stimuli clk/reset
 
   */
+  bool ok = false;
+
   if (direction == Input) return false;
   if (iface->isReferenceInterface()) return false;
   ConnectedInterface* connIface = AI_TO_CON(iface);
   if (connIface->getConnectedFrom() != NULL) return false;
-  // special case
+
+  // special case, NB: never tests clocks
   if ((getOwner()->getName().startsWith("clkrstgen")) && (iface->getOwner()->isStimuliBlock())) {
     if ((direction == Output) && (iface->getDirection() == Input)) {
       if ((purpose == AbstractInterface::Clock) && (iface->getPurpose() == AbstractInterface::Clock)) return true;
@@ -117,23 +129,48 @@ bool FunctionalInterface::canConnectTo(AbstractInterface *iface) {
   // first case: interface of blocks within the same group
   if (getOwner()->getParent() == iface->getOwner()->getParent()) {
 
-    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+
+
+    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   // second case: iface = interface of the group that contains owner of this
   else if (getOwner()->getParent() == iface->getOwner()) {
-    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   else if ((getOwner()->isStimuliBlock()) && (iface->getOwner()->isTopGroupBlock())) {
-    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
   }
 
+  if (ok) {
+    if (testClock) {
+      int dom1 = -1,dom2 = -2;
+      try {
+        dom1 = getClockDomain();
+        dom2 = iface->getClockDomain();
+      }
+      catch(Exception e) {
+        cerr << qPrintable(fctName) << " - " << qPrintable(e.getMessage()) << endl;
+        return false;
+      }
+      if (dom1 != dom2) {
+        cout << "cannot connect interface that are in different clock domains" << endl;
+        return false;
+      }
+    }
+    return true;
+  }
   return false;
 
 }
 
-bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) {
+bool FunctionalInterface::canConnectFrom(AbstractInterface *iface, bool testClock) {
+
+  static QString fctName = "FunctionalInterface::canConnectFrom()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
   /* NOTE :
      necessary conditions :
@@ -151,11 +188,13 @@ bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) {
 
      special case : clk/reset of stimuli can connect from clk/reset of clkrstgen
   */
+  bool ok = false;
+
   if (direction == Output) return false;
   if (iface->isReferenceInterface()) return false;
   if (connectedFrom != NULL) return false;
 
-  // special case
+  // special case, NB: never tests clock
   if ((iface->getOwner()->getName().startsWith("clkrstgen")) && (getOwner()->isStimuliBlock())) {
     if ((direction == Input) && (iface->getDirection() == Output)) {
       if ((purpose == AbstractInterface::Clock) && (iface->getPurpose() == AbstractInterface::Clock)) return true;
@@ -163,14 +202,32 @@ bool FunctionalInterface::canConnectFrom(AbstractInterface *iface) {
     }
   }
 
-  if (getOwner()->getParent() == iface->getOwner()->getParent()) {
-
-    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+  if (getOwner()->getParent() == iface->getOwner()->getParent()) {    
+    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   else if (getOwner()->getParent() == iface->getOwner()) {
-    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
+  }
+
+  if (ok) {
+    if (testClock) {
+      int dom1 = -1,dom2 = -2;
+      try {
+        dom1 = getClockDomain();
+        dom2 = iface->getClockDomain();
+      }
+      catch(Exception e) {
+        cerr << qPrintable(e.getMessage()) << endl;
+        return false;
+      }
+      if (dom1 != dom2) {
+        cout << "cannot connect interfaces that are in different clock domains" << endl;
+        return false;
+      }
+    }
+    return true;
   }
 
   return false;
@@ -195,21 +252,27 @@ int FunctionalInterface::getClockDomain() throw(Exception) {
     if (connFrom == NULL) throw(Exception(IFACE_INVALID_CLKFREQ,this));
 
     if (connFrom->getOwner()->isFunctionalBlock()) {
-      QString name = connFrom->getOwner()->getName();
-      cout << "conn from clkrstgen: searching for clkdomain in " << qPrintable(name) << endl;
-      name.remove(0,10);
-      bool ok;
-      idClock = name.toInt(&ok);
+      QString domName = connFrom->getOwner()->getName();
+      domName.remove(0,10);
+      cout << "conn from clkrstgen: searching for clkdomain in " << qPrintable(domName) << endl;
+
+      bool ok = true;
+      idClock = domName.toInt(&ok);
+      cout << "id clock = " << idClock << endl;
       if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
     }
-    else {
-      QString name = connFrom->getName();
-      cout << "conn from group: searching for clkdomain in " << qPrintable(name) << endl;
-      name.remove(0,8);
-      bool ok;
-      idClock = name.toInt(&ok);
+    else if (connFrom->getOwner()->isGroupBlock()) {
+      QString domName = connFrom->getName();
+      domName.remove(0,8);
+      cout << "conn from group: searching for clkdomain in " << qPrintable(domName) << endl;
+
+      bool ok = true;
+      idClock = domName.toInt(&ok);
       if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
     }
+    else {
+      cout << "abnormal case while searching for clkdomain" << endl;
+    }
   }
 
   return idClock;
diff --git a/FunctionalInterface.h b/FunctionalInterface.h
index 3c70703..6d0731a 100644
--- a/FunctionalInterface.h
+++ b/FunctionalInterface.h
@@ -45,8 +45,8 @@ public :
 
   // testers
   bool isFunctionalInterface();
-  bool canConnectTo(AbstractInterface* iface);
-  bool canConnectFrom(AbstractInterface* iface);
+  bool canConnectTo(AbstractInterface* iface, bool testClock);
+  bool canConnectFrom(AbstractInterface* iface, bool testClock);
 
   // others
 
diff --git a/Graph.cpp b/Graph.cpp
index d0c11cc..2b43baa 100644
--- a/Graph.cpp
+++ b/Graph.cpp
@@ -3,6 +3,8 @@
 #include "ReferenceBlock.h"
 #include "FunctionalBlock.h"
 #include "SpecialBlock.h"
+#include "BlockParameter.h"
+#include "ConnectedInterface.h"
 
 Graph::Graph() {
   topGroup = NULL;
@@ -275,6 +277,7 @@ void Graph::generateTestbench(const QString &projectName, const QString &benchFi
   out << "use IEEE.numeric_std.all;" << endl;
   out << "entity " << projectName << "_tb is" << endl;
   out << "end entity " << projectName << "_tb;" << endl << endl;
+
   out << "architecture " << projectName << "_tb_1 of " << projectName << "_tb is" << endl << endl;
 
   out << "  component clock_gen" << endl;
@@ -287,7 +290,238 @@ void Graph::generateTestbench(const QString &projectName, const QString &benchFi
   out << "  end component;" << endl << endl;
 
   topGroup->generateComponent(out,false);
+  foreach(FunctionalBlock* block, stimulis) {
+    block->generateComponent(out,false);
+  }
+
+  out << "  ----------------------------" << endl;
+  out << "  --  SIGNALS" << endl;
+  out << "  ----------------------------" << endl << endl;
+
+  out << "  -- signals to reset stimulis" << endl;
+  foreach(FunctionalBlock* block, stimulis) {
+    out << "  signal reset_" << block->getName() << " : std_logic;" << endl;
+  }
+  out << endl;
+
+  out << "  -- signals for external clocks/reset" << endl;
+  for(int i=0;i<clocks.size();i++) {
+    out << "  signal ext_clk_" << i << " : std_logic;" << endl;
+    out << "  signal ext_reset_" << i << " : std_logic;" << endl;
+  }
+  out << endl;
+
+  // signals out of stimulis blocks
+  foreach(FunctionalBlock* block, stimulis) {
+    /* NB: normally, a stimuli has at least an input interface of type data
+      that is used to trigger the generation. It is necessarily called start.
+      It may have an additional input that is necessarily called stop.
+     */
+    try {
+      out << "  -- signals from input ports of " << block->getName() << endl;
+      QList<AbstractInterface*> listInputs = block->getInputs();
+      foreach(AbstractInterface* iface, listInputs) {
+        if (iface->getPurpose() == AbstractInterface::Data) {
+          out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
+        }
+      }
+    }
+    catch(Exception e) {
+      throw(e);
+    }
+    try {
+      out << "  -- signals from output ports of " << block->getName() << endl;
+      QList<AbstractInterface*> listOutputs = block->getOutputs();
+      foreach(AbstractInterface* iface, listOutputs) {
+        if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+          out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
+        }
+      }
+    }
+    catch(Exception e) {
+      throw(e);
+    }
+    out << endl;
+  }
+  out << endl;
+
+  // signals out of top group
+  try {
+    out << "  -- signals from output ports of " << topGroup->getName() << endl;
+    QList<AbstractInterface*> listOutputs = topGroup->getOutputs();
+    foreach(AbstractInterface* iface, listOutputs) {
+      if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+        out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
+      }
+    }
+  }
+  catch(Exception e) {
+    throw(e);
+  }
+  out << endl;
+
+  // signals out of top group
+  try {
+    out << "  -- signals from inout ports of " << topGroup->getName() << endl;
+    QList<AbstractInterface*> listBidirs = topGroup->getBidirs();
+    foreach(AbstractInterface* iface, listBidirs) {
+      if (iface->getPurpose() == AbstractInterface::Data) {
+        out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
+      }
+    }
+  }
+  catch(Exception e) {
+    throw(e);
+  }
+  out << endl;
+
+  out << "begin" << endl;
+  // for now assign all external resets to fixed 0 because of clkrstgen in top group
+  for(int i=0;i<clocks.size();i++) {
+    out << "  ext_reset_" << i << " <= '0';" << endl;
+  }
+  out << endl;
+  // generate clock instances
+  for(int i=0;i<clocks.size();i++) {
+    double halfPer = 500.0/clocks.at(i);
+    out << "  clock_" << i << " : clock_gen" << endl;
+    out << "    generic map (" << endl;
+    out << "      Tps => " << halfPer << " ns" << endl;
+    out << "      )" << endl;
+    out << "    port map (" << endl;
+    out << "      phase => ext_clk_" << i << endl;
+    out << "      );" << endl << endl;
+  }
+  // generate instances of stimulis
+  foreach(FunctionalBlock* block, stimulis) {
+    try {
+      out << "  " << block->getName() << "_1 : " << block->getName() << endl;
+
+      QList<BlockParameter*> listGenerics = block->getGenericParameters();
+      QList<AbstractInterface*> listInputs = block->getInputs();
+      QList<AbstractInterface*> listOutputs = block->getOutputs();
+
+      if (!listGenerics.isEmpty()) {
+        out << "    generic map (" << endl;
+        int i;
+        for(i=0;i<listGenerics.size()-1;i++) {
+          out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl;
+        }
+        out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl;
+        out << "    )" << endl;
+      }
+
+      out << "    port map (" << endl;
+      QString portMap = "";
+
+      for(int i=0;i<listInputs.size();i++) {
+        ConnectedInterface* connIface = AI_TO_CON(listInputs.at(i));
+        if ( (connIface->getPurpose() == AbstractInterface::Data) || (connIface->getPurpose() == AbstractInterface::Control)) {
+          portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
+        }
+        else if (connIface->getPurpose() == AbstractInterface::Clock) {
+          // get the "fake" clkrstgen from which it is connected
+          ConnectedInterface* fromIface = connIface->getConnectedFrom();
+          QString clkrstName = fromIface->getOwner()->getName();
+          clkrstName.remove(0,10);
+          portMap += "      " + connIface->getName() + " => ext_clk_" + clkrstName + ",\n";
+        }
+        else if (connIface->getPurpose() == AbstractInterface::Reset) {
+          portMap += "      " + connIface->getName() + " => reset_" + block->getName()+",\n";
+        }
+      }
+      for(int i=0;i<listOutputs.size();i++) {
+        ConnectedInterface* connIface = AI_TO_CON(listOutputs.at(i));
+        portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
+      }
+      portMap.chop(2);
+      out << portMap << endl;
+
+
+      out << "    );" << endl;
+    }
+    catch(Exception e) {
+      throw(e);
+    }
+    out << endl;
+  }
+  out << endl;
+  // generate instance of top group
+  try {
+    out << "  " << topGroup->getName() << "_1 : " << topGroup->getName() << endl;
+
+    QList<BlockParameter*> listGenerics = topGroup->getGenericParameters();
+    QList<AbstractInterface*> listInputs = topGroup->getInputs();
+    QList<AbstractInterface*> listOutputs = topGroup->getOutputs();
+    QList<AbstractInterface*> listBidirs = topGroup->getBidirs();
+
+    if (!listGenerics.isEmpty()) {
+      out << "    generic map (" << endl;
+      int i;
+      for(i=0;i<listGenerics.size()-1;i++) {
+        out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl;
+      }
+      out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl;
+      out << "    )" << endl;
+    }
+
+    out << "    port map (" << endl;
+    QString portMap = "";
+
+    for(int i=0;i<listInputs.size();i++) {
+      ConnectedInterface* connIface = AI_TO_CON(listInputs.at(i));
+      if ( (connIface->getPurpose() == AbstractInterface::Data) || (connIface->getPurpose() == AbstractInterface::Control)) {
+        ConnectedInterface* fromIface = connIface->getConnectedFrom();
+        portMap += "      " + connIface->getName() + " => " + fromIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
+      }
+      else if ( (connIface->getPurpose() == AbstractInterface::Clock) || (connIface->getPurpose() == AbstractInterface::Reset)) {
+        portMap += "      " + connIface->getName() + " => " + connIface->getName() + ",\n";
+      }
+    }
+    for(int i=0;i<listOutputs.size();i++) {
+      ConnectedInterface* connIface = AI_TO_CON(listOutputs.at(i));
+      portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
+    }
+    for(int i=0;i<listBidirs.size();i++) {
+      ConnectedInterface* connIface = AI_TO_CON(listBidirs.at(i));
+      portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
+    }
+    portMap.chop(2);
+    out << portMap << endl;
+
+
+    out << "    );" << endl;
+  }
+  catch(Exception e) {
+    throw(e);
+  }
+  out << endl;
+
+  // generate process for stimulis
+  foreach(FunctionalBlock* block, stimulis) {
+    // getting the start input
+    AbstractInterface* startIface = block->getIfaceFromName("start");
+    if (startIface == NULL) continue;
+    double per = 1000.0/startIface->getClockFrequency();
+    QString startName = block->getName()+"_start";
+    out << "  from_" << block->getName() << " : process" << endl;
+    out << "    variable pclk : time := " << per << " ns;" << endl;
+    out << "  begin" << endl;
+    out << "    reset_" << block->getName() << " <= '0';" << endl;
+    out << "    " << startName << " <= '0';" << endl;
+    out << "    wait for 2*pclk;" << endl;
+    out << "    reset_" << block->getName() << " <= '1';" << endl;
+    out << "    wait for 1*pclk;" << endl;
+    out << "    reset_" << block->getName() << " <= '0';" << endl;
+    out << "    wait for 5*pclk;" << endl;
+    out << "    " << startName << " <= '1';" << endl;
+    out << "    wait for pclk;" << endl;
+    out << "    " << startName << " <= '0';" << endl << endl;
+    out << "    wait for 100000 us;" << endl;
+    out << "  end process from_" << block->getName() << ";" << endl;
+  }
 
+  out << "end architecture " << projectName << "_tb_1;" << endl;
   vhdlBench.close();
 
 }
diff --git a/GroupBlock.cpp b/GroupBlock.cpp
index d3ff0ed..d78a28e 100644
--- a/GroupBlock.cpp
+++ b/GroupBlock.cpp
@@ -7,6 +7,7 @@
 #include <sstream>
 #include "Parameters.h"
 #include "DelayInputModifier.h"
+#include "Graph.h"
 
 int GroupBlock::counter = 1;
 
@@ -484,16 +485,18 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(
   out << "  --  SIGNALS" << endl;
   out << "  ----------------------------" << endl << endl;
 
-  // signals to synchronize inputs
-  out << "  -- signals to synchronize inputs" << endl;
-  foreach(AbstractInterface* iface, getInputs()) {
-    if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
-      QString name = iface->toVHDL(AbstractInterface::Signal,0);
-      name.replace(" : ","_sync : ");
-      out << "  signal " << name<< endl;
+  // if this is top group, signals to synchronize inputs
+  if (topGroup) {
+    out << "  -- signals to synchronize inputs" << endl;
+    foreach(AbstractInterface* iface, getInputs()) {
+      if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+        QString name = iface->toVHDL(AbstractInterface::Signal,0);
+        name.replace(" : ","_sync : ");
+        out << "  signal " << name<< endl;
+      }
     }
+    out << endl;
   }
-  out << endl;
 
   // "normal" signals
   foreach(AbstractBlock* block, blocks) {
@@ -504,7 +507,7 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(
         if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
           out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
         }
-        else if (block->getName() == "clkrstgen") {
+        else if (block->getName().startsWith("clkrstgen")) {
           if ((iface->getPurpose() == AbstractInterface::Clock)||(iface->getPurpose() == AbstractInterface::Reset)) {
             out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
           }
@@ -668,36 +671,54 @@ void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(
   }
 
   if (topGroup) {
-    // generate input sync process
+    // generate input sync process for each clock domain
     out << "  -- process to synchronize inputs of top group" << endl;
-    out << "sync_inputs : process(from_clkrstgen_clk,from_clkrstgen_reset)" << endl;
-    out << "  begin" << endl;
-    out << "    if from_clkrstgen_reset = '1' then" << endl;
-    foreach(AbstractInterface* iface, getInputs()) {
-      if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
-        if (iface->getWidth() == 0) {
-          out << "      " << name << "_" << iface->getName() << "_sync <= '0';" << endl;
-        }
-        else {
-          out << "      " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl;
+    for(int i=0;i<graph->getClocks().size();i++) {
+      // check if there are some inputs that must be sync with clock domain i
+      bool mustSync = false;
+      foreach(AbstractInterface* iface, getInputs()) {
+        if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+          if (iface->getClockDomain() == i) {
+            mustSync = true;
+            break;
+          }
         }
       }
-    }
-    out << "    elsif rising_edge(from_clkrstgen_clk) then" << endl;
-    foreach(AbstractInterface* iface, getInputs()) {
-      if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
-        if (iface->getWidth() == 0) {
-          out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
+      if (mustSync) {
+        out << "sync_inputs_" << i << " : process(from_clkrstgen_" << i << "_clk,from_clkrstgen_" << i << "_reset)" << endl;
+        out << "  begin" << endl;
+        out << "    if from_clkrstgen_" << i << "_reset = '1' then" << endl;
+        foreach(AbstractInterface* iface, getInputs()) {
+          if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+            if (iface->getClockDomain() == i) {
+              if (iface->getWidth() == 0) {
+                out << "      " << name << "_" << iface->getName() << "_sync <= '0';" << endl;
+              }
+              else {
+                out << "      " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl;
+              }
+            }
+          }
         }
-        else {
-          out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
+        out << "    elsif rising_edge(from_clkrstgen_" << i << "_clk) then" << endl;
+        foreach(AbstractInterface* iface, getInputs()) {
+          if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
+            if (iface->getClockDomain() == i) {
+              if (iface->getWidth() == 0) {
+                out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
+              }
+              else {
+                out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
+              }
+            }
+          }
         }
+        out << "    end if;" << endl;
+        out << "  end process sync_inputs_" << i << ";" << endl;
+
+        out << endl;
       }
     }
-    out << "    end if;" << endl;
-    out << "  end process sync_inputs;" << endl;
-
-    out << endl;
   }
 
   out << "end architecture rtl;" << endl;
diff --git a/GroupInterface.cpp b/GroupInterface.cpp
index bfeb1ff..db80b91 100644
--- a/GroupInterface.cpp
+++ b/GroupInterface.cpp
@@ -10,6 +10,7 @@ GroupInterface::GroupInterface(AbstractBlock* _owner, const QString& _name, int
   if ((purpose == Clock) || (purpose == Reset)) {
     type = Boolean;
   }
+  clkIfaceType = InheritedName;
 }
 
 bool GroupInterface::isGroupInterface() {
@@ -44,7 +45,7 @@ int GroupInterface::getWidth() {
   return w;
 }
 
-bool GroupInterface::canConnectTo(AbstractInterface *iface) {
+bool GroupInterface::canConnectTo(AbstractInterface *iface, bool testClock) {
 
   /* NOTE :
      necessary conditions :
@@ -62,32 +63,53 @@ bool GroupInterface::canConnectTo(AbstractInterface *iface) {
         2.1 - this is an output, iface is an output of the group
         2.2 - both are inout
      
-
+      NB: testClock is useless since a group interface has always a clkIfaceType inherited.
+      Thus, it is always possible
 
   */
+  bool ok = false;
+
   if (iface->isReferenceInterface()) return false;
   ConnectedInterface* connIface = AI_TO_CON(iface);
   if (connIface->getConnectedFrom() != NULL) return false;
 
   if (this->getOwner() == iface->getOwner()->getParent()) {
-    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
 
   }
   else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) {
-    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Output) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   else if (this->getOwner()->getParent() == iface->getOwner()) {
-    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   
+  if (ok) {
+    if (testClock) {
+      int dom1 = -1,dom2 = -2;
+      try {
+        dom1 = getClockDomain();
+        dom2 = iface->getClockDomain();
+      }
+      catch(Exception e) {
+        cerr << qPrintable(e.getMessage()) << endl;
+        return false;
+      }
+      if (dom1 != dom2) {
+        cout << "cannot connect interface that are in different clock domains" << endl;
+        return false;
+      }
+    }
+    return true;
+  }
 
   return false;
 }
 
-bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
+bool GroupInterface::canConnectFrom(AbstractInterface *iface, bool testClock) {
 
   /* NOTE :
      necessary conditions :
@@ -106,24 +128,45 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
         2.2 - both are inout
      4 - this is owned by top group and iface is an output of a source block           
   */
+  bool ok = false;
+
   if (iface->isReferenceInterface()) return false;
   if (getConnectedFrom() != NULL) return false;
 
   if (this->getOwner() == iface->getOwner()->getParent()) {
-    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Output) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
 
   }
   else if (this->getOwner()->getParent() == iface->getOwner()->getParent()) {
-    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   else if (this->getOwner()->getParent() == iface->getOwner()) {
-    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) return true;
-    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Input) && (iface->getDirection() == Input) && (purpose == iface->getPurpose())) ok = true;
+    if ((direction == InOut) && (iface->getDirection() == InOut) && (purpose == iface->getPurpose())) ok = true;
   }
   else if ((getOwner()->isTopGroupBlock()) && (iface->getOwner()->isStimuliBlock())) {
-    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) return true;
+    if ((direction == Input) && (iface->getDirection() == Output) && (purpose == iface->getPurpose())) ok = true;
+  }
+
+  if (ok) {
+    if (testClock) {
+      int dom1 = -1,dom2 = -2;
+      try {
+        dom1 = getClockDomain();
+        dom2 = iface->getClockDomain();
+      }
+      catch(Exception e) {
+        cerr << qPrintable(e.getMessage()) << endl;
+        return false;
+      }
+      if (dom1 != dom2) {
+        cout << "cannot connect interface that are in different clock domains" << endl;
+        return false;
+      }
+    }
+    return true;
   }
 
   return false;
@@ -131,29 +174,60 @@ bool GroupInterface::canConnectFrom(AbstractInterface *iface) {
 
 int GroupInterface::getClockDomain() throw(Exception) {
 
+  /* For clk/rst interfaces, the clock domain can be deduced
+     from the interface name.
+     Otherwise, we can search backward/forward for a functional
+     interface. Since a group interface cannot exist if it is not
+     connected to and/or from a functional interface (either directly
+     or through a sequence of subgroups) there is at least such a functional
+     interface.
+   */
   int idClock = -1;
-
-  GroupInterface* iface = NULL;
-  if (clkIfaceType == ClockName) {
-    iface = AI_TO_GRP(getClockIface());
-  }
-  else if ((direction == Input) && (purpose == Clock)) {
-    iface = this;
-  }
-
-  if ( iface != NULL) {
-
-    QString name = iface->getName();
-    name.remove(0,8);
+  if ((purpose == Clock) || (purpose == Reset)) {
+    QString domName = name;
+    domName.remove(0,8);
     bool ok;
-    idClock = name.toInt(&ok);
+    idClock = domName.toInt(&ok);
     if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
-
+  }
+  else {
+    // start by searching backward
+    ConnectedInterface* connFrom = connectedFrom;
+    while ((connFrom != NULL) && (connFrom->isGroupInterface())) {
+      connFrom = connFrom->getConnectedFrom();
+    }
+    if (connFrom != NULL) {
+      idClock = connFrom->getClockDomain();
+    }
+    //searching forward
+    else {
+      QList<ConnectedInterface*> lstIfaces = getForwardFunctionalInterfaces(this);
+      if (lstIfaces.isEmpty()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
+      foreach(ConnectedInterface* iface, lstIfaces) {
+        // test if all ifaces are in the same clock domain
+        if (idClock == -1) {
+          idClock = iface->getClockDomain();
+        }
+        else if (idClock != iface->getClockDomain()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
+      }
+    }
   }
 
   return idClock;
 }
 
+QList<ConnectedInterface*> GroupInterface::getForwardFunctionalInterfaces(GroupInterface* groupIface) {
+  QList<ConnectedInterface*> lstIfaces;
+  foreach(ConnectedInterface* iface, groupIface->getConnectedTo()) {
+    if (iface->isFunctionalInterface()) {
+      lstIfaces.append(iface);
+    }
+    else if (iface->isGroupInterface()) {
+      lstIfaces.append(getForwardFunctionalInterfaces(AI_TO_GRP(iface)));
+    }
+  }
+  return lstIfaces;
+}
 
 void GroupInterface::connectionsValidation(QStack<AbstractInterface*> *interfacetoValidate, QList<AbstractInterface*> *validatedInterfaces) throw(Exception) {
     cout << "group interface connection validation" << endl;
diff --git a/GroupInterface.h b/GroupInterface.h
index 35f0916..6bedd67 100644
--- a/GroupInterface.h
+++ b/GroupInterface.h
@@ -10,6 +10,7 @@
 #include "Exception.h"
 class Exception;
 
+
 using namespace std;
 using namespace Qt;
 
@@ -43,11 +44,13 @@ public :
 
   // testers
   bool isGroupInterface();
-  bool canConnectTo(AbstractInterface* iface);
-  bool canConnectFrom(AbstractInterface* iface);
+  bool canConnectTo(AbstractInterface* iface, bool testClock);
+  bool canConnectFrom(AbstractInterface* iface, bool testClock);
 
   // others
   AbstractInterface *clone();
+  QList<ConnectedInterface *> getForwardFunctionalInterfaces(GroupInterface* groupIface);
+
   void connectionsValidation(QStack<AbstractInterface *> *interfacetoValidate, QList<AbstractInterface *> *validatedInterfaces) throw(Exception);
 
 };
diff --git a/InterfacePropertiesDialog.cpp b/InterfacePropertiesDialog.cpp
index cc0a3ad..fb76c71 100644
--- a/InterfacePropertiesDialog.cpp
+++ b/InterfacePropertiesDialog.cpp
@@ -32,6 +32,8 @@ InterfacePropertiesDialog::InterfacePropertiesDialog(InterfaceItem *_inter, QWid
   layProp->addWidget(new QLabel(inter->refInter->getPurposeString()), 5, 1);
   layProp->addWidget(new QLabel("Type :"), 6, 0);
   layProp->addWidget(new QLabel(inter->refInter->getTypeString()), 6, 1);
+  layProp->addWidget(new QLabel("related to clock :"), 7, 0);
+  layProp->addWidget(new QLabel(inter->refInter->getClockIfaceString()), 7, 1);
 
   QHBoxLayout* layBottom = new QHBoxLayout;
   layBottom->addStretch();
diff --git a/MainWindow.cpp b/MainWindow.cpp
index 99f13bb..6f4716a 100644
--- a/MainWindow.cpp
+++ b/MainWindow.cpp
@@ -311,9 +311,14 @@ void MainWindow::save(QString projectFile) {
   params->save(projectFile);
 }
 
-void MainWindow::slotLoadProject(){
+void MainWindow::slotLoadProject(QString fileName){
 
-  params->projectFile = QFileDialog::getOpenFileName(0, "select a project file", "save/",tr("sauvegardes (*.xml)"));
+  if (fileName == "") {
+    params->projectFile = QFileDialog::getOpenFileName(0, "select a project file", "save/",tr("sauvegardes (*.xml)"));
+  }
+  else {
+    params->projectFile = fileName;
+  }
 
   if(! params->projectFile.isEmpty()){
     GroupWidget* topGroup = dispatcher->loadProject(params->projectFile);
diff --git a/MainWindow.h b/MainWindow.h
index 96fab67..613b3d1 100644
--- a/MainWindow.h
+++ b/MainWindow.h
@@ -121,10 +121,10 @@ private:
 public slots:
   void enableProjectActions(bool enbMenu, quint16 mask = 0, quint8 op = 0); // default : add nothing
   void enableAnalysisActions(bool enbMenu, quint16 mask = 0, quint8 op = 0); // default : add nothing
+  void slotLoadProject(QString fileName = "");
 
 private slots:
-  void slotNewProject();
-  void slotLoadProject();
+  void slotNewProject();  
   void slotSaveProject();
   void slotSaveAsProject();
   bool slotCloseProject();
diff --git a/ReferenceBlock.cpp b/ReferenceBlock.cpp
index 553955b..56a34db 100644
--- a/ReferenceBlock.cpp
+++ b/ReferenceBlock.cpp
@@ -80,7 +80,7 @@ void ReferenceBlock::load(QDomElement &elt) throw(Exception) {
 
   // create interfaces that correspond to a wishbone parameter, if any.
   try {
-    createInterfaceForParameters();    
+    createInterfaceForWishbone();
   }
   catch(int err) {
     throw(err);
@@ -220,7 +220,7 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
   int purpose;
   QString multStr;
   int mult;
-  AbstractInterface* inter;
+  ReferenceInterface* iface;
 
   if ((elt.isNull()) || (elt.tagName() != "interfaces")) throw (Exception(BLOCKFILE_CORRUPTED));
 
@@ -236,9 +236,12 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
     purposeStr = eltInput.attribute("purpose","none");
     if (purposeStr == "clock") {
       nameStr = eltInput.attribute("name","none");
-      inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1);
-      inputs.append(inter);
-      clocks.append(inter);
+      iface = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Clock, "boolean", "1", AbstractInterface::LittleEndian, 1);
+      if (! iface->checkSetClockIface(nameStr)) {
+        throw (Exception(BLOCKFILE_CORRUPTED));
+      }
+      inputs.append(iface);
+      clocks.append(iface);
     }
   }
   cout << "number of clocks: " << clocks.size() << endl;
@@ -270,15 +273,19 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
       multStr = eltInput.attribute("multiplicity","none");
       mult = ReferenceInterface::translateMultiplicity(multStr);
 
-      inter = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
+      iface = new ReferenceInterface(this,nameStr, AbstractInterface::Input, purpose, typeStr, widthStr, endianess, mult);
       if (clockStr == "none") {
-        // no clock given, take the first one (hope that there is a single one !)
+        if (clocks.size() > 1) {
+          // if several clocks, the associated one MUST be given
+          throw (Exception(BLOCKFILE_CORRUPTED));
+        }
+        // no clock given, take the single one
         clockStr = clocks.at(0)->getName();
       }
-      if (! inter->setClockIface(clockStr)) {
+      if (! iface->checkSetClockIface(clockStr)) {
         throw (Exception(BLOCKFILE_CORRUPTED));
       }
-      inputs.append(inter);
+      inputs.append(iface);
     }
   }
   // getting each control
@@ -289,13 +296,17 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
     nameStr = eltInput.attribute("iface","none");
     AbstractInterface* dataIface = getIfaceFromName(nameStr);
     if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
-    nameStr = dataIface->getName()+"_enb";
-    inter = new ReferenceInterface(this,nameStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
-    if (!inter->setAssociatedIface(dataIface)) {
+    QString nameEnbStr = dataIface->getName()+"_enb";
+    iface = new ReferenceInterface(this,nameEnbStr,AbstractInterface::Input, AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
+    if (!iface->setAssociatedIface(dataIface)) {
       throw (Exception(BLOCKFILE_CORRUPTED));      
     }
-    cout << "created a control input named " << qPrintable(inter->getName()) << endl;
-    inputs.append(inter);
+    clockStr = dataIface->getClockIfaceString();
+    if (! iface->checkSetClockIface(clockStr)) {
+      throw (Exception(BLOCKFILE_CORRUPTED));
+    }
+    cout << "created a control input named " << qPrintable(iface->getName()) << endl;
+    inputs.append(iface);
   }
   QDomElement eltOutputs = eltInputs.nextSiblingElement("outputs");
   QDomNodeList listNodeOutputs = eltOutputs.elementsByTagName("output");
@@ -323,15 +334,20 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
     multStr = eltOutput.attribute("multiplicity","none");
     mult = ReferenceInterface::translateMultiplicity(multStr);
 
-    inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
+    iface = new ReferenceInterface(this,nameStr,AbstractInterface::Output, purpose,typeStr,widthStr, endianess, mult);
     if (clockStr == "none") {
-      // no clock given, take the first one (hope that there is a single one !)
+      if (clocks.size() > 1) {
+        // if several clocks, the associated one MUST be given
+        throw (Exception(BLOCKFILE_CORRUPTED));
+      }
+      // no clock given, take the single one
       clockStr = clocks.at(0)->getName();
     }
-    if (! inter->setClockIface(clockStr)) {
+    if (! iface->checkSetClockIface(clockStr)) {
       throw (Exception(BLOCKFILE_CORRUPTED));
     }
-    outputs.append(inter);
+
+    outputs.append(iface);
   }
   // getting each control
   QDomNodeList listNodeOutCtl = eltOutputs.elementsByTagName("control");
@@ -342,12 +358,16 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
     AbstractInterface* dataIface = getIfaceFromName(nameStr);
     if (dataIface == NULL) throw (Exception(BLOCKFILE_CORRUPTED));
     nameStr = dataIface->getName()+"_enb";
-    inter = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
-    if (!inter->setAssociatedIface(dataIface)) {
+    iface = new ReferenceInterface(this,nameStr,AbstractInterface::Output, AbstractInterface::Control,"boolean","1",AbstractInterface::LittleEndian, 1);
+    if (!iface->setAssociatedIface(dataIface)) {
       throw (Exception(BLOCKFILE_CORRUPTED));      
     }
-    cout << "created a control output named " << qPrintable(inter->getName()) << endl;
-    outputs.append(inter);
+    clockStr = dataIface->getClockIfaceString();
+    if (! iface->checkSetClockIface(clockStr)) {
+      throw (Exception(BLOCKFILE_CORRUPTED));
+    }
+    cout << "created a control output named " << qPrintable(iface->getName()) << endl;
+    outputs.append(iface);
   }
 
   QDomElement eltBidirs = eltInputs.nextSiblingElement("bidirs");
@@ -375,19 +395,24 @@ void ReferenceBlock::loadInterfaces(QDomElement &elt) throw(Exception) {
     multStr = eltBidir.attribute("multiplicity","none");
     mult = ReferenceInterface::translateMultiplicity(multStr);
 
-    inter = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
+    iface = new ReferenceInterface(this,nameStr,AbstractInterface::InOut, purpose,typeStr,widthStr, endianess, mult);
     if (clockStr == "none") {
-      // no clock given, take the first one (hope that there is a single one !)
+      if (clocks.size() > 1) {
+        // if several clocks, the associated one MUST be given
+        throw (Exception(BLOCKFILE_CORRUPTED));
+      }
+      // no clock given, take the single one
       clockStr = clocks.at(0)->getName();
     }
-    if (! inter->setClockIface(clockStr)) {
+    if (! iface->checkSetClockIface(clockStr)) {
       throw (Exception(BLOCKFILE_CORRUPTED));
     }
-    bidirs.append(inter);
+
+    bidirs.append(iface);
   }
 }
 
-void ReferenceBlock::createInterfaceForParameters() throw(Exception){
+void ReferenceBlock::createInterfaceForWishbone() throw(Exception){
   ReferenceInterface* iface = NULL;
   foreach(BlockParameter* param, params) {
     
@@ -484,7 +509,7 @@ QDataStream& operator<<(QDataStream &out, const ReferenceBlock &b) {
       toWrite << iface->getClockIfaceString();
     }
   }
-  // secondly, write other ifaces
+  // thirdly, write other ifaces
   for(int i=0; i<b.inputs.size(); i++){
     ReferenceInterface *iface = (ReferenceInterface *)(b.inputs.at(i));
     if ((iface->getPurpose() != AbstractInterface::Control) && (iface->getPurpose() != AbstractInterface::Clock)) {
@@ -624,13 +649,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
     QString clk;
     in >> clkType;
     in >> clk;
-    if (clkType == AbstractInterface::ParameterName) {
-      clk = "$"+clk;
-    }
-    if (! iface->setClockIface(clk)) {
-      cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
-    }
-
+    iface->setClockIfaceName(clk);
+    iface->setClockIfaceType(clkType);
     b.inputs.append(iface);
     if (iface->getPurpose() == AbstractInterface::Data) {
       QString ctlRefName = iface->getName()+"_enb";
@@ -664,12 +684,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
     QString clk;
     in >> clkType;
     in >> clk;
-    if (clkType == AbstractInterface::ParameterName) {
-      clk = "$"+clk;
-    }
-    if (! iface->setClockIface(clk)) {
-      cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
-    }
+    iface->setClockIfaceName(clk);
+    iface->setClockIfaceType(clkType);
     b.outputs.append(iface);
     if (iface->getPurpose() == AbstractInterface::Data) {
       QString ctlRefName = iface->getName()+"_enb";      
@@ -703,12 +719,8 @@ QDataStream& operator>>(QDataStream &in, ReferenceBlock &b) {
     QString clk;
     in >> clkType;
     in >> clk;
-    if (clkType == AbstractInterface::ParameterName) {
-      clk = "$"+clk;
-    }
-    if (! iface->setClockIface(clk)) {
-      cerr << "Abnormal case while reading a reference block in library: cannot set ref clock for an interface" << endl;
-    }
+    iface->setClockIfaceName(clk);
+    iface->setClockIfaceType(clkType);
     b.bidirs.append(iface);
   }
 
diff --git a/ReferenceBlock.h b/ReferenceBlock.h
index 2aca879..63dca3c 100644
--- a/ReferenceBlock.h
+++ b/ReferenceBlock.h
@@ -61,7 +61,7 @@ private:
   void loadInformations(QDomElement &elt) throw(Exception);
   void loadParameters(QDomElement &elt) throw(Exception);
   void loadInterfaces(QDomElement &elt) throw(Exception);
-  void createInterfaceForParameters() throw(Exception);
+  void createInterfaceForWishbone() throw(Exception);
 
   friend QDataStream &operator<<(QDataStream &out, const ReferenceBlock &b);
   friend QDataStream &operator>>(QDataStream &in, ReferenceBlock &b);
diff --git a/ReferenceInterface.cpp b/ReferenceInterface.cpp
index fdebeaa..ae5613b 100644
--- a/ReferenceInterface.cpp
+++ b/ReferenceInterface.cpp
@@ -1,5 +1,6 @@
 #include "ReferenceInterface.h"
 #include "AbstractBlock.h"
+#include "BlockParameter.h"
 
 ReferenceInterface::ReferenceInterface(AbstractBlock* _owner)  throw(Exception) : AbstractInterface(_owner) {
   if (_owner->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
@@ -76,3 +77,92 @@ int ReferenceInterface::getClockDomain() throw(Exception) {
 
   throw(Exception(IFACE_INVALID_TYPE,this));
 }
+
+/* NOTE on clock associated to each interface:
+
+   Each interface must be associated to a clock so that blast can determine
+   if there are no problems with clocks domains. This clock must correspond to
+   the name of a clock interface owned by the same block or to a user parameter
+   for which the value indicate the clock frequency. This latter case is used only
+   for input interfaces of blocks that will be directly linked to the outside of top group
+   (NB: directly only means that there are no others functional blocks between the
+   mentionnned block and the outside, but it can be within subgroups) and with these interfaces
+   that receives a data signal synchronized on an outside clock that is not provided to the design.
+   For example, on the APF27 board, there is a link between imx and spartan 3 and signals are at 133MHz.
+   But there is no clock provided to the FPGA.
+
+   Reference blocks are created with:
+     - input clocks are associated to themselves.
+     - output clocks are associated to one of the clock.
+     - reset are associated to one of the clock (since they are generated
+     by clkrstgen, they are really synchronized with a clock)
+     - all other signals are associated to one of the clock or to a parameter
+   The name of the associated clock is given in the xml description file. If not
+   indicated it is by default the name of the input clock. In case of there are
+   several input clocks, the xml is incoherent if other signal do not indicate the name of
+   the associated clock.
+
+   Functional block are created by cloning a reference thus they follow the same rules as
+   reference blocks.
+
+   A group is created with interfaces that have an inherited clock name thus, setting a name
+   is meaningless and an iterative process must be used to retrieve the clock domain from
+   the interface that is connected from the group interface (cf. GroupBlock::getClockDomain())
+
+   The following method checks if these rules are applied correctly.
+
+*/
+bool ReferenceInterface::checkSetClockIface(QString _name) {
+
+  /* 3 cases :
+     - this is a clock input: name must be the same as the iface name
+     - this is an output clock or reset: name must be an existing clock name.
+     - other cases: name must ba a parameter name or an exisiting clock name
+
+    NB: if it's a parameter it must be prepend with a $.
+  */
+  if ((purpose == Clock) && (direction == Input)) {
+    if (_name == name) {
+      clkIfaceName = _name;
+      clkIfaceType = ClockName;
+      return true;
+    }
+  }
+  else if ((purpose == Reset) || ((purpose == Clock) && (direction == Output))) {
+    QList<AbstractInterface*> clocks = owner->getInterfaces(Input, Clock);
+    foreach(AbstractInterface* iface, clocks) {
+      if (iface->getName() == _name) {
+        clkIfaceName = _name;
+        clkIfaceType = ClockName;
+        return true;
+      }
+    }
+  }
+  else {
+    if (_name.at(0) == '$') {
+      _name.remove(0,1);
+      QList<BlockParameter* > params = owner->getUserParameters();
+      foreach(BlockParameter* p, params) {
+        if (p->getName() == _name) {
+          clkIfaceName = _name;
+          clkIfaceType = ParameterName;
+          return true;
+        }
+      }
+    }
+    else {
+      QList<AbstractInterface*> clocks = owner->getInterfaces(Input, Clock);
+      foreach(AbstractInterface* iface, clocks) {
+        if (iface->getName() == _name) {
+          clkIfaceName = _name;
+          clkIfaceType = ClockName;
+          return true;
+        }
+      }
+    }
+  }
+  clkIfaceName = "";
+  clkIfaceType = NoName;
+  return false;
+}
+
diff --git a/ReferenceInterface.h b/ReferenceInterface.h
index cf54f4a..68c0179 100644
--- a/ReferenceInterface.h
+++ b/ReferenceInterface.h
@@ -31,6 +31,7 @@ public :
   bool isReferenceInterface();
 
   // others
+  bool checkSetClockIface(QString _name);
 
   static int translatePurpose(const QString& txt);  
   static int translateMultiplicity(const QString& txt);
diff --git a/blast.cpp b/blast.cpp
index 35dd592..763a8d2 100644
--- a/blast.cpp
+++ b/blast.cpp
@@ -12,6 +12,9 @@ int main(int argc, char *argv[]) {
     MainWindow w;
 
     w.show();
+    if (argc == 2) {
+      w.slotLoadProject(argv[1]);
+    }
 
     return a.exec();
 }
diff --git a/blast.creator.user b/blast.creator.user
index 34b8287..fb924e9 100644
--- a/blast.creator.user
+++ b/blast.creator.user
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 4.2.0, 2018-05-09T18:21:40. -->
+<!-- Written by QtCreator 4.2.0, 2018-05-15T19:43:34. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
diff --git a/blastconfig.xml b/blastconfig.xml
index 26ec97a..05d683a 100644
--- a/blastconfig.xml
+++ b/blastconfig.xml
@@ -2,12 +2,12 @@
 <config>
   <categories>
     <category name="root" id="0" parent="-1"/>
-    <category name="math" id="1" parent="0"/>
+    <category name="stimulis" id="1" parent="0"/>
     <category name="trigonemetric" id="2" parent="1"/>
     <category name="arithmetics" id="3" parent="1"/>
     <category name="filters" id="4" parent="0"/>
     <category name="wishbone" id="5" parent="0"/>
-    <category name="generators" id="6" parent="0"/>
+    <category name="math" id="6" parent="0"/>
     <category name="observers" id="7" parent="0"/>
     <category name="special" id="8" parent="0"/>
     <category name="clock related" id="9" parent="8"/>
diff --git a/lib/implementations/clkdomain_convert_1024x8_impl.xml b/lib/implementations/clkdomain_convert_1024x8_impl.xml
index 6046ebe..aa35dfe 100644
--- a/lib/implementations/clkdomain_convert_1024x8_impl.xml
+++ b/lib/implementations/clkdomain_convert_1024x8_impl.xml
@@ -60,8 +60,6 @@ if empty = '0' then
 end if;
 end if;
 end process read_fifo;
-
-end architecture clkdomain_convert_1024x8_1;
 </architecture>
   <patterns>
     <delta value="1"/>
diff --git a/lib/implementations/impls.bmf b/lib/implementations/impls.bmf
index 3fc15fe..6802074 100644
Binary files a/lib/implementations/impls.bmf and b/lib/implementations/impls.bmf differ
diff --git a/lib/implementations/read_csv_impl.xml b/lib/implementations/read_csv_impl.xml
index aa5e00f..389bbb3 100644
--- a/lib/implementations/read_csv_impl.xml
+++ b/lib/implementations/read_csv_impl.xml
@@ -62,7 +62,7 @@ new_line &lt;= '0';
 item_count := 0;
 line_count := 0;
 last_line := '0';
-out_enb &lt;= '0';
+@{out_val_enb} &lt;= '0';
 dly_item_count := 0;
 dly_line_count := 0;
 item_count_enb := '0';
@@ -70,7 +70,7 @@ line_count_enb := '0';
 
 elsif rising_edge(@{clk}) then
 
-out_enb &lt;= '0';
+@{out_val_enb} &lt;= '0';
 
 if do_read = '1' then
 
@@ -101,7 +101,7 @@ end if;
 else
 read(l, in_val);
 out_s &lt;= to_unsigned(in_val, item_width);
-out_enb &lt;= '1';
+@{out_val_enb} &lt;= '1';
 item_count := item_count + 1;
 if (item_count &lt; item_per_line) then
 read(l, comma);
@@ -121,7 +121,7 @@ end if;
 end if;
 end if;
 
-elsif start_read = '1' then
+elsif @{start} = '1' then
 -- reading the first line
 readline(in_data, l);
 line_count := line_count + 1;
@@ -132,8 +132,6 @@ do_read &lt;= '1';
 end if;
 
 end process read_data;
-
-end architecture read_csv_a;
 </architecture>
   <patterns>
     <delta value="$nb_lines*$item_per_line"/>
diff --git a/lib/references/clkdomain_convert_1024x8.xml b/lib/references/clkdomain_convert_1024x8.xml
index b6e19c4..59f84ed 100644
--- a/lib/references/clkdomain_convert_1024x8.xml
+++ b/lib/references/clkdomain_convert_1024x8.xml
@@ -7,15 +7,12 @@
       This IP allows to pass 8 bits values from a clock domain to another. It uses a FIFO of 1024 entries.
     </description>
   </informations>
-  <parameters>
-    <parameter type="real" context="generic" name="clk_in_freq" value="100"/>
-    <parameter type="real" context="generic" name="clk_out_freq" value="100"/>
-  </parameters>
+  <parameters />
   <interfaces>
     <inputs>
       <input width="1" multiplicity="1" endian="little" type="boolean" name="clk_in" purpose="clock"/>
       <input width="1" multiplicity="1" endian="little" type="boolean" name="clk_out" purpose="clock"/>
-      <input width="1" multiplicity="1" endian="little" type="boolean" name="reset" purpose="reset"/>
+      <input width="1" multiplicity="1" endian="little" type="boolean" name="reset" purpose="reset" clock="clk_in"/>
       <input width="8" multiplicity="1" endian="little" type="natural" name="data_in" purpose="data" clock="clk_in"/>
       <control iface="data_in"/>
     </inputs>
diff --git a/lib/references/generator-cst.xml b/lib/references/generator-cst.xml
index 2ddf876..112add7 100644
--- a/lib/references/generator-cst.xml
+++ b/lib/references/generator-cst.xml
@@ -4,7 +4,7 @@
     <name>
       generator-cst
     </name>
-    <category ids="6" />  
+    <category ids="1" />  
     <description>
       generates V consecutives constant values, followed by Z idle cycles    
     </description>    
@@ -21,6 +21,7 @@
     <inputs>
       <input name="clk" width="1" purpose="clock" />
       <input name="rst" width="1" purpose="reset" />
+      <input purpose="data" name="start" width="1" multiplicity="1" endian="little" type="boolean"/>
     </inputs>
     <outputs>
       <output name="data_o" width="$data_width"/>
diff --git a/lib/references/generator-img.xml b/lib/references/generator-img.xml
index dfc18eb..0c350f6 100644
--- a/lib/references/generator-img.xml
+++ b/lib/references/generator-img.xml
@@ -4,7 +4,7 @@
     <name>
       generator-img
     </name>
-    <category ids="6" />  
+    <category ids="1" />  
     <description>
       generates a RGB image, reading if from a csv file
     </description>    
@@ -21,6 +21,7 @@
     <inputs>
       <input name="clk" width="1" purpose="clock" />
       <input name="rst" width="1" purpose="reset" />
+      <input purpose="data" name="start" width="1" multiplicity="1" endian="little" type="boolean"/>
     </inputs>
     <outputs>
       <output name="r_o" width="8"/>
diff --git a/lib/references/read_csv.xml b/lib/references/read_csv.xml
index c8fd7f1..d738413 100644
--- a/lib/references/read_csv.xml
+++ b/lib/references/read_csv.xml
@@ -2,7 +2,7 @@
 <block version="0.1" special="source">
   <informations>
     <name>read_csv</name>
-    <category ids="6"/>
+    <category ids="1"/>
     <description>
       read a csv file
     </description>
@@ -20,6 +20,8 @@
     <inputs>
       <input purpose="clock" name="clk" width="1" multiplicity="1" endian="little" type="boolean"/>
       <input purpose="reset" name="reset" width="1" multiplicity="1" endian="little" type="boolean"/>
+      <input purpose="data" name="start" width="1" multiplicity="1" endian="little" type="boolean"/>
+      
     </inputs>
     <outputs>
       <output purpose="data" name="out_val" width="$item_width" multiplicity="1" endian="little" type="expression"/>
diff --git a/lib/references/references.bmf b/lib/references/references.bmf
index ffc13f1..bdb7010 100644
Binary files a/lib/references/references.bmf and b/lib/references/references.bmf differ