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

Private GIT Repository
added admittance computation
[blast.git] / FunctionalBlock.cpp
index 23d43b9033c5c6157afdeb3ceb5c1a90fcddde58..ac27de40a0168d25129cb50334badc96c7d6e3df 100644 (file)
@@ -117,10 +117,10 @@ bool FunctionalBlock::createPatterns() {
   \r
   cout << "create patterns for block " << qPrintable(name) << endl;\r
   evaluator = new ArithmeticEvaluator();\r
-  bool ok = true;\r
-  ok = ok & createDelta();\r
+  bool ok = true;  \r
   if (! isGeneratorBlock()) {\r
-    if (ok) ok = ok & createConsumptionPattern();\r
+    ok = ok & createDelta();\r
+    if (ok) ok = ok & createConsumptionPattern();    \r
     if (ok) ok = ok & createProductionCounter();\r
   }\r
   if (ok) ok = ok & createProductionPattern();\r
@@ -134,8 +134,12 @@ bool FunctionalBlock::createDelta() {
   cout << "call to " << qPrintable(fctName) << endl;\r
 #endif \r
   \r
-  QString deltaStr = implementation->getDelta();\r
+  QString deltaStr = implementation->getDelta();  \r
   cout << "delta for " << qPrintable(name) << " = " << qPrintable(deltaStr) << endl;\r
+  if (deltaStr.isEmpty()) {\r
+    delta = -1;\r
+    return true;\r
+  }\r
   \r
   // look for parameter names\r
   bool ok = true;\r
@@ -154,6 +158,7 @@ bool FunctionalBlock::createConsumptionPattern() {
   cout << "call to " << qPrintable(fctName) << endl;\r
 #endif\r
   \r
+  lengthCP = -1;\r
   bool ok = true; \r
   QHash<QString,QString> consPattern = implementation->getConsumptionPattern();  \r
   \r
@@ -164,10 +169,15 @@ bool FunctionalBlock::createConsumptionPattern() {
       cerr << "no consumption pattern for reference interface " << qPrintable(refName) << endl;\r
       return false;\r
     }\r
-    QList<char>* pattern = expandPattern(consPattern.value(refName),&ok);    \r
-    \r
+    QList<char>* pattern = expandPattern(consPattern.value(refName),&ok);        \r
     if (!ok) return false;\r
-    consumptionPattern.insert(connIface,pattern);        \r
+    consumptionPattern.insert(connIface,pattern);\r
+    if (lengthCP == -1) {\r
+      lengthCP = pattern->size();\r
+    }\r
+    else {\r
+      if (pattern->size() != lengthCP) return false;\r
+    }\r
   }        \r
   return true;\r
 }\r
@@ -178,6 +188,7 @@ bool FunctionalBlock::createProductionPattern() {
   cout << "call to " << qPrintable(fctName) << endl;\r
 #endif\r
   \r
+  lengthPP = -1;\r
   bool ok = true; \r
   QHash<QString,QString> prodPattern = implementation->getProductionPattern();  \r
   \r
@@ -190,7 +201,13 @@ bool FunctionalBlock::createProductionPattern() {
     }\r
     QList<char>* pattern = expandPattern(prodPattern.value(refName),&ok);\r
     if (!ok) return false;\r
-    productionPattern.insert(connIface,pattern);    \r
+    productionPattern.insert(connIface,pattern);\r
+    if (lengthPP == -1) {\r
+      lengthPP = pattern->size();\r
+    }\r
+    else {\r
+      if (pattern->size() != lengthPP) return false;\r
+    }\r
   }    \r
   return true;\r
 }\r
@@ -379,6 +396,121 @@ double FunctionalBlock::evaluateExpression(const QString& expression, bool* ok)
   return result;\r
 }\r
 \r
+void FunctionalBlock::createInputPattern() {\r
+  lengthIP = -1;\r
+  foreach(AbstractInterface* iface, getControlInputs()) {      \r
+    ConnectedInterface* connIface = AI_TO_CON(iface);\r
+    QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();\r
+    if (lengthIP == -1) {\r
+      lengthIP = out->size();\r
+    }\r
+    else {\r
+      if (out->size() < lengthIP) lengthIP = out->size();\r
+    }\r
+    if (out->size() > 0) {\r
+      QList<char>* in = new QList<char>(*out);\r
+      foreach(char c, *in) {\r
+        cout << (int)c;\r
+      }\r
+      cout << endl;\r
+\r
+      inputPattern.insert(connIface,in);\r
+    }\r
+    else {\r
+      inputPattern.insert(connIface,NULL);\r
+    }      \r
+  }  \r
+}\r
+\r
+bool FunctionalBlock::createAdmittance(int nbExec) {\r
+  static QString fctName = "FunctionalBlock::createAdmittance()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  bool ok = true;\r
+  // firstly, copy CP in AP\r
+  QMapIterator<AbstractInterface*,QList<char>* > iterC(consumptionPattern);\r
+  while (iterC.hasNext()) {\r
+    iterC.next();\r
+    QList<char>* pattern = new QList<char>(*(iterC.value()));\r
+    admittance.insert(iterC.key(), pattern);    \r
+  }\r
+  lengthAP = lengthCP;\r
+  int clock = 0;  \r
+  cout << "trigger 1 at c.c. 0" << endl;\r
+  for(int i=1;i<nbExec;i++) {\r
+    // searching for the clock cycle for which a new exec starts\r
+    int nbGroup = 0;\r
+    while ((clock < lengthAP) && (nbGroup < delta)) {\r
+      if (isValidDataGroup(admittance,clock)) nbGroup+=1;\r
+      clock += 1;\r
+    }\r
+    while ((clock < lengthAP) && (! isValidDataGroup(admittance,clock))) clock+=1;\r
+    cout << "trigger " << (i+1) << " at c.c. " << clock << endl;\r
+    int sc = clock;\r
+    // combine CP with AP at sc\r
+    for(int j=0;j<lengthCP;j++) {\r
+      // first case : column of CP must be placed beyond AP's end.\r
+      if (sc == lengthAP) {\r
+        cout << i << "," << j << " append in AP at " << sc << endl;\r
+        appendToPattern(consumptionPattern,j,admittance,1);\r
+        lengthAP += 1;\r
+        sc += 1;              \r
+      }\r
+      // second case : CP and AP can be combined directly (i.e. no X | 1 to do)\r
+      else if (canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
+        cout << i << "," << j << " combine at " << sc << endl;\r
+        combinePatterns(consumptionPattern,j,admittance,sc);\r
+        sc += 1;\r
+      }\r
+      // third case : CP has an X column\r
+      else if (isOnlyXDataGroup(consumptionPattern,j)) {\r
+        cout << i << "," << j << " shift rigth AP to combine at " << sc << endl;\r
+        shiftRightPattern(admittance,sc);\r
+        lengthAP += 1;\r
+        if (! canCombinePatterns(consumptionPattern,j,admittance,sc)) {\r
+          cerr << "Abnormal case when combining AP and CP" << endl;\r
+        }\r
+        combinePatterns(consumptionPattern,j,admittance,sc);        \r
+        sc += 1;\r
+      }\r
+      // fourth case : AP has an X column\r
+      else if (isOnlyXDataGroup(admittance,sc)) {\r
+        cout << i << "," << j << " jump c.c. for CP at " << sc << endl;        \r
+        sc += 1;\r
+        j -= 1;\r
+      }\r
+      else {\r
+        cout << "AP and CP are not consistent" << endl;\r
+        return false;\r
+      }\r
+    }\r
+  }\r
+  \r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::checkInputPatternCompatibility() {\r
+  static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
+#ifdef DEBUG_FCTNAME\r
+  cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+  \r
+  bool ok = true;\r
+  // firstly, create input pattern\r
+  createInputPattern();      \r
+  // if some patterns are not available, end now, returning false\r
+  if (lengthIP == 0) {\r
+    clearInputPattern();\r
+    return false;\r
+  }\r
+  int nbExec = getNumberOfExecution();\r
+  ok = createAdmittance(nbExec);\r
+  if (!ok) return false;\r
+  \r
+  return true;\r
+}\r
+\r
 bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
   static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
 #ifdef DEBUG_FCTNAME\r
@@ -407,48 +539,23 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
   else {\r
     cout << "computing output pattern of " << qPrintable(name) << endl;\r
     \r
-    // collect the input patterns for each input \r
-    QMap<AbstractInterface*,QList<char>* > inputPattern;    \r
-    int minLen = -1;\r
-    foreach(AbstractInterface* iface, getControlInputs()) {      \r
-      ConnectedInterface* connIface = AI_TO_CON(iface);\r
-      QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();\r
-      if (minLen == -1) {\r
-        minLen = out->size();\r
-      }\r
-      else {\r
-        if (out->size() < minLen) minLen = out->size();\r
+    // in case of inputPattern not created, do it\r
+    if (lengthIP <= 0) {\r
+      // collect the input patterns for each input    \r
+      createInputPattern();    \r
+      // if some patterns are not available, end now, returning false\r
+      if (lengthIP == 0) {\r
+        clearInputPattern();\r
+        return false;\r
       }\r
-      if (out->size() > 0) {\r
-        QList<char>* in = new QList<char>(*out);\r
-        foreach(char c, *in) {\r
-          cout << (int)c;\r
-        }\r
-        cout << endl;\r
-\r
-        inputPattern.insert(connIface,in);\r
-      }\r
-      else {\r
-        inputPattern.insert(connIface,NULL);\r
-      }      \r
-    }\r
-    // if some patterns are not available, end now, returning false\r
-    if (minLen == 0) {\r
-      QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
-      while (iterI.hasNext()) {\r
-        iterI.next();\r
-        QList<char>* pattern = iterI.value();        \r
-        if (pattern != NULL) delete pattern;\r
-      }     \r
-      return false;\r
+      cout << "input pattern array initialized with min. len " << lengthIP << endl;\r
     }\r
-    cout << "input pattern array initialized with min. len " << minLen << endl;\r
     \r
     // initialize the output pattern    \r
-    int lengthOP = 0;\r
+    lengthOP = 0;\r
     foreach(AbstractInterface* iface, getControlOutputs()) {\r
       FunctionalInterface* connIface = AI_TO_FUN(iface);      \r
-      lengthOP = minLen+productionPattern.value(connIface)->size();\r
+      lengthOP = lengthIP+productionPattern.value(connIface)->size();\r
       QList<char>* pattern = new QList<char>();\r
       for(int i=0;i<lengthOP;i++) pattern->append(0);\r
       connIface->setOutputPattern(pattern);\r
@@ -459,10 +566,10 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
     int clock = 0;\r
     nbExec = 0;\r
     // search for the beginning of the first execution.\r
-    while ((clock < minLen) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
+    while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
     cout << "found 1st exec clock: " << clock << endl;\r
     \r
-    while (clock < minLen) {\r
+    while (clock < lengthIP) {\r
       // initialize counters for current execution.\r
       int p = 0; // index in production pattern\r
       int o = 0; // clock+o will give the clock cycle of each output group\r
@@ -480,7 +587,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
         int gap = 0; // count the number of extra null columns\r
         // search for PC(m) valid input group in IP\r
         while (nip < productionCounter.at(m)) {\r
-          if (clock+cip < minLen) {\r
+          if (clock+cip < lengthIP) {\r
             if (isValidDataGroup(inputPattern,clock+cip)) nip += 1;\r
             cip += 1;\r
             gap += 1;\r
@@ -513,7 +620,7 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
       // search for the next exec.\r
       clock += 1;      \r
       nip = 0;\r
-      while ((clock < minLen) && (nip < delta)) {\r
+      while ((clock < lengthIP) && (nip < delta)) {\r
         if (isValidDataGroup(inputPattern,clock)) nip += 1;\r
         if (nip < delta) clock += 1;\r
       }\r
@@ -525,13 +632,8 @@ bool FunctionalBlock::computeOutputPattern(int nbExec) {
       lengthOP -= 1;\r
     }\r
 \r
-    // clear input pattern    \r
-    QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
-    while (iterI.hasNext()) {\r
-      iterI.next();\r
-      QList<char>* pattern = iterI.value();        \r
-      if (pattern != NULL) delete pattern;\r
-    }     \r
+    // clear input pattern\r
+    clearInputPattern();\r
   }\r
   return true;\r
 }\r
@@ -598,6 +700,17 @@ void FunctionalBlock::removeDataGroup(QMap<AbstractInterface *, QList<char> *> &
   }\r
 }\r
 \r
+void FunctionalBlock::shiftRightPattern(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
+  QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
+  while (iterSrc.hasNext()) {\r
+    iterSrc.next();    \r
+    QList<char>* srcPat = iterSrc.value();\r
+    if (offset < srcPat->size()) {\r
+      srcPat->insert(offset,0);\r
+    }\r
+  }\r
+}\r
+\r
 bool FunctionalBlock::isValidDataGroup(const QMap<AbstractInterface *, QList<char> *> &pattern, int offset) {\r
   QMapIterator<AbstractInterface*, QList<char>* > iterSrc(pattern);  \r
   while (iterSrc.hasNext()) {\r
@@ -627,6 +740,8 @@ void FunctionalBlock::clearConsumptionPattern() {
     QList<char>* pattern = iterP.value();\r
     if (pattern != NULL) delete pattern;\r
   }\r
+  consumptionPattern.clear();\r
+  lengthCP = -1;      \r
 }  \r
 \r
 void FunctionalBlock::clearProductionPattern() {\r
@@ -636,4 +751,40 @@ void FunctionalBlock::clearProductionPattern() {
     QList<char>* pattern = iterP.value();\r
     if (pattern != NULL) delete pattern;\r
   }\r
+  productionPattern.clear();\r
+  lengthPP = -1;\r
 }  \r
+\r
+void FunctionalBlock::clearInputPattern() {\r
+  \r
+  QMapIterator<AbstractInterface*,QList<char>* > iterI(inputPattern);\r
+  while (iterI.hasNext()) {\r
+    iterI.next();\r
+    QList<char>* pattern = iterI.value();\r
+    if (pattern != NULL) delete pattern;\r
+  }\r
+  inputPattern.clear();\r
+  lengthIP = -1;\r
+}\r
+\r
+int FunctionalBlock::getNumberOfExecution() {\r
+  /* NB: this method returns the number of executions that have been started\r
+     but not necessary completed.\r
+  */\r
+  if (delta <= 0) return 0;\r
+  int nbExec = 0;\r
+  int offset = 0;\r
+  // search for the first exec.\r
+  while ((offset < lengthIP) && (! isValidDataGroup(inputPattern,offset))) offset++;\r
+  if (offset == lengthIP) return 0;\r
+  nbExec = 1;\r
+  int nbGroup = 0;\r
+  for(int i = offset;i<lengthIP;i++) {\r
+    if (isValidDataGroup(inputPattern,offset)) nbGroup++;\r
+    if (nbGroup == delta+1) {\r
+      nbExec += 1;\r
+      nbGroup = 1;\r
+    }\r
+  }      \r
+  return nbExec;  \r
+}\r