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

Private GIT Repository
added generator-cst
[blast.git] / FunctionalBlock.cpp
index f54708419ae9422e8b9a1b867397ec5f477a9d4f..5731794da37211ed6872f1b7c88ca3c703e74a79 100644 (file)
@@ -13,6 +13,19 @@ FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference
   reference = _reference;\r
   parent = _parent;\r
   name = reference->getName();\r
   reference = _reference;\r
   parent = _parent;\r
   name = reference->getName();\r
+  consumptionPattern = NULL;\r
+  lengthCP = 0;\r
+  nbConsumingPorts = 0;\r
+  productionPattern = NULL;\r
+  lengthPP = 0;\r
+  nbProducingPorts = 0;\r
+  if (reference->getImplementations().isEmpty()) {\r
+    implementation = NULL;\r
+    cout << "block has no implementation" << endl;\r
+  }\r
+  else {\r
+    implementation = reference->getImplementations().at(0);\r
+  }\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -41,30 +54,54 @@ bool FunctionalBlock::isFunctionalBlock() {
   return true;\r
 }\r
 \r
   return true;\r
 }\r
 \r
+bool FunctionalBlock::isSourceBlock() {\r
+  if (parent == NULL) return true;\r
+  return false;\r
+}\r
+\r
 void FunctionalBlock::populate() {\r
   int i;\r
   BlockParameter* p;\r
   AbstractInterface* inter;\r
 \r
 void FunctionalBlock::populate() {\r
   int i;\r
   BlockParameter* p;\r
   AbstractInterface* inter;\r
 \r
+  // create parameters from reference block\r
   QList<BlockParameter*> lstParam = reference->getParameters();\r
   for(i=0;i<lstParam.size();i++) {\r
     p = lstParam.at(i)->clone();\r
     addParameter(p);\r
   }\r
 \r
   QList<BlockParameter*> lstParam = reference->getParameters();\r
   for(i=0;i<lstParam.size();i++) {\r
     p = lstParam.at(i)->clone();\r
     addParameter(p);\r
   }\r
 \r
-  QList<AbstractInterface *> lstInter = reference->getInterfaces();\r
-  for(i=0;i<lstInter.size();i++) {\r
+  // create interfaces from reference block\r
+  QList<AbstractInterface *> lstRef = reference->getInterfaces();\r
+  // store relation between functional and reference\r
+  QHash<AbstractInterface *, AbstractInterface *> hashIface;\r
+  for(i=0;i<lstRef.size();i++) {\r
     try {\r
     try {\r
-      inter = new FunctionalInterface(this, (ReferenceInterface*)lstInter.at(i));\r
+      inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));\r
     }\r
     catch(Exception e) {\r
       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
       exit(1);\r
     }\r
     }\r
     catch(Exception e) {\r
       cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;\r
       exit(1);\r
     }\r
+    hashIface.insert(lstRef.at(i),inter);\r
 \r
     addInterface(inter);\r
   }\r
 \r
     addInterface(inter);\r
   }\r
-\r
+    \r
+  AbstractInterface* funCtlIface = NULL;\r
+  AbstractInterface* funDataIface = NULL;\r
+  \r
+  for(i=0;i<lstRef.size();i++) {    \r
+    AbstractInterface* refIface = lstRef.at(i);    \r
+    if (refIface->getPurpose() == AbstractInterface::Control) {\r
+      funCtlIface = hashIface.value(refIface);\r
+      funDataIface = hashIface.value(refIface->getAssociatedIface());\r
+      if (! funCtlIface->setAssociatedIface(funDataIface)) {\r
+        cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;\r
+        exit(1);\r
+      }       \r
+    }\r
+  }\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -72,7 +109,284 @@ QString FunctionalBlock::getReferenceXmlFile() {
     return ((ReferenceBlock *)reference)->getXmlFile();\r
 }\r
 \r
     return ((ReferenceBlock *)reference)->getXmlFile();\r
 }\r
 \r
-QString FunctionalBlock::getReferenceHashMd5()\r
-{\r
+QString FunctionalBlock::getReferenceHashMd5() {\r
     return ((ReferenceBlock *)reference)->getHashMd5();\r
 }\r
     return ((ReferenceBlock *)reference)->getHashMd5();\r
 }\r
+\r
+bool FunctionalBlock::createPatterns() {\r
+  evaluator = new ArithmeticEvaluator();\r
+  bool ok = true;\r
+  ok = ok & createDelta();\r
+  if (ok) ok = ok & createConsumptionPattern();\r
+  if (ok) ok = ok & createProductionCounter();\r
+  if (ok) ok = ok & createProductionPattern();\r
+  delete evaluator;\r
+  return ok;\r
+}\r
+\r
+bool FunctionalBlock::createDelta() {\r
+  QString delta = implementation->getDelta();\r
+  cout << "delta for " << qPrintable(name) << " = " << qPrintable(delta) << endl;\r
+  \r
+  // look for parameter names\r
+  QHash<QString,double> vars;\r
+  QRegularExpression re("[$][a-zA-Z0-9_]+");\r
+  QRegularExpressionMatchIterator matcher = re.globalMatch(delta);\r
+  while(matcher.hasNext()) {\r
+    QRegularExpressionMatch m = matcher.next();\r
+    QString var = m.captured(0);\r
+    cout << qPrintable(var) << endl;\r
+    vars.insert(var,0.0);    \r
+  }\r
+  QHashIterator<QString,double> iterV(vars);\r
+  while (iterV.hasNext()) {\r
+    iterV.next();\r
+    QString var = iterV.key();\r
+    QString paramName = var.remove(0,1);\r
+    BlockParameter* param = reference->getParameterFromName(paramName);\r
+    cout << "param = " << qPrintable(param->getStringValue()) << endl;\r
+    if (param == NULL) {\r
+      cerr << "found an unknown parameter in delta"<< endl;\r
+      return false;\r
+    }\r
+    bool ok;\r
+    int val = param->getIntValue(&ok);\r
+    vars.insert(var,(double)val);\r
+  }\r
+  cout << "set expr " << endl;\r
+  evaluator->setExpression(delta);\r
+  cout << "set vars " << endl;\r
+  evaluator->setVariablesValue(vars);\r
+  double result = evaluator->evaluate();\r
+  cout << "delta = " << result << endl;\r
+   \r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::createConsumptionPattern() {\r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::createProductionPattern() {\r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::createProductionCounter() {\r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::computeOutputPattern(int nbExec) {\r
+  \r
+  /* case 1: the block is a generator for which output pattern\r
+     must be computed for a nbExec following executions\r
+  */\r
+  \r
+  if (nbExec > 0) {\r
+    foreach(AbstractInterface* iface, getControlOutputs()) {\r
+      QList<char> pattern;\r
+      for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();\r
+      iface->setOutputPattern(pattern);\r
+    }    \r
+  }\r
+  else {\r
+    // initialize consumption and production patterns\r
+    initConsumptionPattern();\r
+    initProductionPattern();\r
+    \r
+    // collect the input patterns for each input    \r
+    char** inputPattern = NULL;\r
+    int idIface = 0;\r
+    inputPattern = new char*[nbConsumingPorts];\r
+    int minLen = -1;\r
+    foreach(AbstractInterface* iface, getControlInputs()) {      \r
+      QList<char> in = iface->getConnectedFrom()->getOutputPattern();\r
+      if (minLen == -1) {\r
+        minLen = in.size();\r
+      }\r
+      else {\r
+        if (in.size() < minLen) minLen = in.size();\r
+      }\r
+      if (in.size() > 0) {\r
+        inputPattern[idIface] = new char[in.size()];\r
+        int i = 0;\r
+        foreach(char c, in) inputPattern[idIface][i++] = c;\r
+      }\r
+      else {\r
+        inputPattern[idIface] = NULL;\r
+      }\r
+      idIface += 1;      \r
+    }\r
+    // if some patterns are not available, ens now, returning false\r
+    if (minLen == 0) {\r
+      for(int i=0;i<nbConsumingPorts; i++) {\r
+        if (inputPattern[i] != NULL) delete [] inputPattern[i];\r
+      }\r
+      delete [] inputPattern;\r
+      return false;\r
+    }\r
+    // initialize the output pattern    \r
+    char** outputPattern = NULL;\r
+    outputPattern = new char*[nbProducingPorts];\r
+    int lengthOP = 0;\r
+    idIface = 0;\r
+    foreach(AbstractInterface* iface, getControlOutputs()) {\r
+      lengthOP = minLen+iface->getProductionPattern().size();\r
+      outputPattern[idIface] = new char[lengthOP];\r
+      memset(outputPattern[idIface],0,lengthOP);\r
+      idIface += 1;\r
+    }\r
+    \r
+    int clock = 0;\r
+    nbExec = 0;\r
+    // search for the beginning of the first execution.\r
+    while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;\r
+    \r
+    while (clock < minLen) {\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
+      int cip = 0; // clock+cip give the clock cycle of an input group\r
+      int ccp = 0; // ccp give a column in the consumptio pattern\r
+      int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP\r
+      int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP\r
+      bool cannotCompleteExec = false;\r
+      for(int m=0;m<productionCounter.size();m++) {\r
+        // search for the first production in PP\r
+        while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {\r
+          p += 1;\r
+          o += 1;\r
+        }\r
+        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 (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;\r
+            cip += 1;\r
+            gap += 1;\r
+          }\r
+          else {\r
+            cannotCompleteExec = true;\r
+            break;\r
+          }        \r
+        }\r
+        \r
+        if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
+        \r
+        // search for PC(m) valid input group in IP\r
+        while (ncp < productionCounter.at(m)) {\r
+          if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;\r
+          ccp += 1;\r
+          gap -= 1;\r
+        }\r
+        o += gap; // to take into acocunt of extra null columns\r
+        combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);\r
+        p += 1;\r
+        o += 1;\r
+      }\r
+      \r
+      if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern\r
+      \r
+      // current exec. taken into accunt\r
+      nbExec += 1;\r
+      \r
+      // search for the next exec.\r
+      clock += 1;      \r
+      nip = 0;\r
+      while ((clock < minLen) && (nip < delta)) {\r
+        if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;\r
+        if (nip < delta) clock += 1;\r
+      }\r
+    }\r
+    // find the last valid output data group\r
+    while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;\r
+    \r
+    // copy back outputPattern info each interface\r
+    idIface = 0;\r
+    foreach(AbstractInterface* iface, getControlOutputs()) {\r
+      QList<char> pattern;\r
+      for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);\r
+      iface->setOutputPattern(pattern);      \r
+      idIface += 1;\r
+    }\r
+    \r
+    // clear inputPattern and outputPattern\r
+    for(int i=0;i<nbConsumingPorts; i++) {\r
+      delete [] inputPattern[i];\r
+    }\r
+    delete [] inputPattern;\r
+    for(int i=0;i<nbProducingPorts; i++) {\r
+      delete [] outputPattern[i];\r
+    }\r
+    delete [] outputPattern;\r
+  }\r
+  return true;\r
+}\r
+\r
+bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {\r
+  \r
+  for(int i=0;i<nbPorts;i++) {\r
+    if (pattern[i][clock] == 1) return true;\r
+  }\r
+  return false;  \r
+}\r
+\r
+void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {\r
+  \r
+  for (int i=0;i<nbCols;i++) {\r
+    for(int j=0;j<nbPorts;j++) {\r
+      patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];\r
+    }\r
+  }\r
+  \r
+}\r
+\r
+void FunctionalBlock::clearConsumptionPattern() {\r
+  if (consumptionPattern == NULL) return;\r
+  \r
+  for(int i=0;i<nbConsumingPorts; i++) {\r
+    delete [] consumptionPattern[i];\r
+  }\r
+  delete [] consumptionPattern;      \r
+}\r
+\r
+void FunctionalBlock::clearProductionPattern() {\r
+  if (productionPattern == NULL) return;\r
+  for(int i=0;i<nbProducingPorts;i++) {\r
+    delete [] productionPattern[i];\r
+  }\r
+  delete [] productionPattern;\r
+}\r
+\r
+void FunctionalBlock::initConsumptionPattern() {\r
+  if (consumptionPattern != NULL) clearConsumptionPattern();\r
+  \r
+  nbConsumingPorts = getControlInputs().size();  \r
+  int idIface = 0;\r
+  consumptionPattern = new char*[nbConsumingPorts];  \r
+  foreach(AbstractInterface* iface, getControlInputs()) {\r
+    \r
+    QList<char> in = iface->getConsumptionPattern();\r
+    lengthCP = in.size(); // normally, all inputs have the same lenght for CP\r
+    consumptionPattern[idIface] = new char[lengthCP];\r
+    int i = 0;\r
+    foreach(char c, in) consumptionPattern[idIface][i++] = c;\r
+    idIface += 1;    \r
+  }\r
+}\r
+\r
+void FunctionalBlock::initProductionPattern() {\r
+  if (productionPattern != NULL) clearProductionPattern();\r
+  \r
+  nbProducingPorts = getControlOutputs().size();  \r
+  int idIface = 0;\r
+  productionPattern = new char*[nbProducingPorts];  \r
+  foreach(AbstractInterface* iface, getControlOutputs()) {\r
+    \r
+    QList<char> in = iface->getProductionPattern();\r
+    lengthPP = in.size(); // normally, all inputs have the same lenght for PP\r
+    productionPattern[idIface] = new char[lengthPP];\r
+    int i = 0;\r
+    foreach(char c, in) productionPattern[idIface][i++] = c;\r
+    idIface += 1;    \r
+  }\r
+}\r