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

Private GIT Repository
finished testbench generation
[blast.git] / AbstractInterface.cpp
index a32f78e6d8c0d5130bcfc1ea48f977a01574bd02..83aa4c399e46373c5703ec518513bcb63b7d0bca 100644 (file)
@@ -2,10 +2,11 @@
 #include "BlockParameterPort.h"
 #include "AbstractBlock.h"
 #include "Parameters.h"
+#include "Graph.h"
 
 AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
 
-  owner = _owner;
+  owner = _owner;  
   name = "";
   width = "1";
   direction = Input;
@@ -13,6 +14,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner) {
   type = Boolean;
   endianess = LittleEndian;
   associatedIface = NULL;
+  clkIfaceName = "";
+  clkIfaceType = NoName;
 
 }
 
@@ -26,6 +29,8 @@ AbstractInterface::AbstractInterface(AbstractBlock* _owner, const QString& _name
   type = typeFromString(_type);
   endianess = _endianess;
   associatedIface = NULL;
+  clkIfaceName = "";
+  clkIfaceType = NoName;
 }
 
 AbstractInterface::AbstractInterface(AbstractInterface* other) {
@@ -37,6 +42,8 @@ AbstractInterface::AbstractInterface(AbstractInterface* other) {
   purpose = other->purpose;
   endianess = LittleEndian;
   associatedIface = NULL;
+  clkIfaceName = other->clkIfaceName;
+  clkIfaceType = other->clkIfaceType;
 }
 
 void AbstractInterface::setName(const QString& _name) {
@@ -59,6 +66,79 @@ bool AbstractInterface::isGroupInterface() {
   return false;
 }
 
+int AbstractInterface::getWidth() {
+
+  bool ok;
+  int w = -1;
+
+  QString expr = width;
+
+  /* CAUTION :
+
+     Since VHDL allows to write std_logic_vector(O downto 0)
+     which is different from std_logic, we have to differentiate
+     a size of 1 that is really a boolean and thus a std_logic, from
+     a std_logic_vector of size 1.
+
+     For this reason, if it is boolean, 0 is returned instead of 1.
+   */
+  if (type == Boolean) {
+    return 0;
+  }
+  else if (type == Natural) {
+    w = width.toInt(&ok);
+    if (!ok) return -1;
+  }
+  else if (type == Expression) {
+
+    QList<BlockParameter*> listGenerics = owner->getGenericParameters();
+    QList<BlockParameter*> listUsers = owner->getUserParameters();
+    QList<BlockParameter*> listPorts = owner->getPortParameters();
+
+    foreach(BlockParameter* p, listUsers) {
+      QString var = "$";
+      var += p->getName();
+      if (width.contains(var)) {
+        int tmp = p->getValue().toInt(&ok);
+        if (!ok) return -1; // user parameter cannot be converted to an int
+        expr.replace(var,p->getValue().toString());
+      }
+    }
+    foreach(BlockParameter* p, listPorts) {
+      QString var = "$";
+      var += p->getName();
+      if (width.contains(var)) {
+        expr.replace(var,p->toVHDL(0,0));
+      }
+    }
+    foreach(BlockParameter* p, listGenerics) {
+      QString var = "$";
+      var += p->getName();
+      if (width.contains(var)) {
+        int tmp = p->getValue().toInt(&ok);
+        if (!ok) return -1;
+        QString s="";
+        s.setNum(tmp);
+        expr.replace(var,s);
+      }
+    }
+    // now evaluate the whole expression
+    ArithmeticEvaluator evaluator;
+
+    try {
+      evaluator.setVariableMarkers("$");
+      evaluator.setExpression(expr);
+      w = (int)(evaluator.evaluate());
+      cout << "iface size :" << w << endl;
+    }
+    catch(int e) {
+      cerr << "invalid expression in size of interface " << qPrintable(name) << " at character " << e << endl;
+      w = -1;
+    }
+  }
+  return w;
+}
+
 QString AbstractInterface::getEndianessString() {
   QString str="unknown";
   switch(endianess){
@@ -113,36 +193,6 @@ QString AbstractInterface::getDirectionString() {
     return str;
 }
 
-double AbstractInterface::getDoubleWidth() throw(QException) {
-
-  static QString fctName = "AbstractInterface::getDoubleWidth()";
- #ifdef DEBUG_FCTNAME
-   cout << "call to " << qPrintable(fctName) << endl;
- #endif
-
-   /*
-    cout << "start AbstractInterface::getDoubleWidth()" << endl;
-    bool ok;
-    double width = getWidth().toDouble(&ok);
-
-    if(!ok){
-      ArithmeticEvaluator *evaluator = new ArithmeticEvaluator;
-      cout << "evaluator created!" << endl;
-      evaluator->setExpression(getWidth());
-      cout << "expression defined!" << endl;
-      foreach(BlockParameter *param, getOwner()->getParameters()){
-        evaluator->setVariableValue(param->getName(), param->getIntValue());
-        cout << "param : " << param->getName().toStdString() << " evaluated!" << endl;
-      }
-      width = evaluator->evaluate();
-      cout << "expression evaluated succefully!" << endl;
-    }
-    cout << "real width : " << width << endl;
-    return width;
-    */
-
-   return 1.0;
-}
 
 void AbstractInterface::setPurpose(int _purpose) {
   if ((_purpose>=Data) && (_purpose <= Wishbone)) {
@@ -164,6 +214,39 @@ bool AbstractInterface::setAssociatedIface(AbstractInterface* iface) {
   return true;
 }
 
+AbstractInterface* AbstractInterface::getClockIface() {
+  if (clkIfaceType == ClockName) {
+    return owner->getIfaceFromName(clkIfaceName);
+  }
+  return NULL;
+}
+
+
+double AbstractInterface::getClockFrequency() throw(Exception) {
+
+  int idClock = -1;
+
+  if (clkIfaceType == ParameterName) {
+    BlockParameter* param = owner->getParameterFromName(clkIfaceName);
+    if (!param->isUserParameter()) throw(Exception(IFACE_INVALID_CLKFREQ,this));
+    bool ok;
+    double freq = param->getDoubleValue(&ok);
+    if (!ok) throw(Exception(IFACE_INVALID_CLKFREQ,this));
+    return freq;
+  }
+  else {
+    try {
+      idClock = getClockDomain();
+    }
+    catch(Exception e) {
+      throw(e);
+    }
+    return owner->getGraph()->getClock(idClock);
+  }
+  return 0.0;
+}
+
+
 
 int AbstractInterface::getIntDirection(QString str) {
     if(str == "input") return Input;
@@ -191,6 +274,9 @@ QString AbstractInterface::getTypeString() {
   else if (type == Expression) {
     return "expression";
   }
+  else if (type == Inherited) {
+    return "inherited";
+  }
   return "invalid_type";
 }
 
@@ -212,88 +298,153 @@ int AbstractInterface::typeFromString(const QString &_type) {
   return ret;
 }
 
-QString AbstractInterface::toVHDL(int context, int flags) throw(Exception) {
+QString AbstractInterface::toVHDL(IfaceVHDLContext context, int flags) throw(Exception) {
 
 
   if (isReferenceInterface()) throw(Exception(IFACE_INVALID_TYPE));
 
-  QString msb = width;
+  int w;
+  QString wStr = "";
   QString ret="";
-  bool ok;
-    cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(msb) << " with type = " << qPrintable(getTypeString()) << endl;
 
-  if ((context == BlockParameter::Entity) || (context == BlockParameter::Component)) {
-
-    QString formatBool = "%1 : %2 std_logic";
-    QString formatVector = "";
-    if (endianess == LittleEndian) formatVector = "%1 : %2 std_logic_vector(%3 downto %4)";
-    else formatVector = "%1 : %2 std_logic_vector(%4 to %3)";
+  bool ok;
+  //cout << "iface " << qPrintable(name) << " must be evaluated to vhdl :" << qPrintable(width) << " with type = " << qPrintable(getTypeString()) << endl;
 
-    if ((flags & BlockParameter::NoComma) == 0) {
-      formatBool.append(";");
-      formatVector.append(";");
-    }
-    QString orientation="";
+  if (context == Instance) {
     if (direction == Input) {
-      orientation = "in";
+      ret = owner->getName()+"_"+name;
     }
     else if (direction == Output) {
-      orientation = "out";
+      ret = "from_"+owner->getName()+"_"+name;
     }
-    else {
-      orientation = "inout";
-    }
-    if (type == Boolean) {
-      ret = formatBool.arg(name).arg(orientation);
+    else if (direction == InOut) {
+      ret = "fromto_"+owner->getName()+"_"+name;
     }
-    else if (type == Natural) {
-      int w = width.toInt(&ok);
+    return ret;
+  }
+
+  // create the width part
+  QString widthStr = "";
+  if (type == Boolean) {
+    widthStr = "std_logic";
+  }
+  else {
+    QString formatWidth = "";
+    if (endianess == LittleEndian) formatWidth = "std_logic_vector(%1 downto %2)";
+    else formatWidth = "std_logic_vector(%2 to %1)";
+
+    if (type == Natural) {
+      w = width.toInt(&ok);
       if (!ok) {
         throw(Exception(INVALID_VALUE));
       }
       else {
         w -= 1;
-        ret = formatVector.arg(name).arg(orientation).arg(w).arg("0");
+        wStr.setNum(w);
+        widthStr = formatWidth.arg(wStr).arg(0);
       }
     }
     else if (type == Expression) {
 
-
-      /* must check the following conditions :
-           - if it contains user/port parameters : must evaluate their numeric value
-           - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated.
-      */
-      QList<BlockParameter*> listGenerics = owner->getGenericParameters();
-      QList<BlockParameter*> listUsers = owner->getUserParameters();
-      QList<BlockParameter*> listPorts = owner->getPortParameters();
-      foreach(BlockParameter* p, listUsers) {
-        QString var = "$";
-        var += p->getName();
-        if (width.contains(var)) {
-          int w = p->getValue().toInt(&ok);
-          if (!ok) throw(Exception(INVALID_VALUE));
-          msb.replace(var,p->getValue().toString());
+      // NB: if for signal, must retrieve the real size, not the one with generics
+      if (context == Signal) {
+        w = getWidth();
+        if (w == -1) throw(Exception(INVALID_VALUE));
+        if (w == 0) {
+          widthStr = "std_logic";
         }
-      }
-      foreach(BlockParameter* p, listPorts) {
-        QString var = "$";
-        var += p->getName();
-        if (width.contains(var)) {          
-          msb.replace(var,p->toVHDL(0,0));
+        else {
+          w--;
+          wStr.setNum(w);
+          widthStr = formatWidth.arg(wStr).arg(0);
         }
       }
-      foreach(BlockParameter* p, listGenerics) {
-        QString var = "$";
-        var += p->getName();
-        if (width.contains(var)) {
-          msb.replace(var,p->getName());
+      else {
+
+        /* must check the following conditions :
+               - if it contains user/port parameters : must evaluate their numeric value
+               - if it contains generic parameters : just remove the $ -> the expression is not arithmetically evaluated.
+          */
+        wStr = width;
+        QList<BlockParameter*> listGenerics = owner->getGenericParameters();
+        QList<BlockParameter*> listUsers = owner->getUserParameters();
+        QList<BlockParameter*> listPorts = owner->getPortParameters();
+        foreach(BlockParameter* p, listUsers) {
+          QString var = "$";
+          var += p->getName();
+          if (width.contains(var)) {
+            w = p->getValue().toInt(&ok);
+            if (!ok) throw(Exception(INVALID_VALUE));
+            wStr.replace(var,p->getValue().toString());
+          }
         }
+        foreach(BlockParameter* p, listPorts) {
+          QString var = "$";
+          var += p->getName();
+          if (width.contains(var)) {
+            wStr.replace(var,p->toVHDL(0,0));
+          }
+        }
+        foreach(BlockParameter* p, listGenerics) {
+          QString var = "$";
+          var += p->getName();
+          if (width.contains(var)) {
+            wStr.replace(var,p->getName());
+          }
+        }
+        wStr += "-1";
+        widthStr = formatWidth.arg(wStr).arg(0);
+      }
+    }
+    else if (type == Inherited) {
+      w = getWidth();
+      if (w == -1) throw(Exception(INVALID_VALUE));
+      if (w == 0) {
+        widthStr = "std_logic";
+      }
+      else {
+        w--;
+        wStr.setNum(w);
+        widthStr = formatWidth.arg(wStr).arg(0);
       }
-      msb += "-1";
-      cout << "iface size :" << qPrintable(msb) << endl;
-      ret = formatVector.arg(name).arg(orientation).arg(msb).arg("0");
     }
   }
+
+  if ((flags & NoComma) == 0) {
+    widthStr.append(";");
+  }
+
+  // generate for an Entity or Component port
+  if ((context == Entity) || (context == Component)) {
+
+    QString formatPort = "%1 : %2 ";
+
+    QString orientation="";
+    if (direction == Input) {
+      orientation = "in";
+    }
+    else if (direction == Output) {
+      orientation = "out";
+    }
+    else {
+      orientation = "inout";
+    }
+
+    ret = formatPort.arg(name).arg(orientation);
+    ret += widthStr;
+  }
+  else if (context == Signal) {
+    if (direction == Output) {
+      ret = "from_"+owner->getName()+"_"+name+" : "+widthStr;
+    }
+    else if (direction == InOut) {
+      ret = "fromto_"+owner->getName()+"_"+name+" : "+widthStr;
+    }
+    else if (direction == Input) {
+      ret = owner->getName()+"_"+name+" : "+widthStr;
+    }
+  }
+
   return ret;
 }