+ evaluator->setVariablesValue(vars);\r
+ double result = 0.0;\r
+ try {\r
+ result = evaluator->evaluate();\r
+ }\r
+ catch(int index) {\r
+ cerr << "Error at index " << index << ": " << qPrintable(evaluator->getError()) << endl;\r
+ throw(Exception(EVAL_INVALID_EXPR,this));\r
+ }\r
+ return result;\r
+}\r
+\r
+void FunctionalBlock::computeAdmittanceDelays() throw(Exception) {\r
+ static QString fctName = "FunctionalBlock::computeAdmittanceDelays()";\r
+#ifdef DEBUG_FCTNAME\r
+ cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+ QList<int> inClock;\r
+ QList<int> delays;\r
+\r
+ clearAdmittanceDelays();\r
+\r
+ // trying to synchronize the first one in AP\r
+ QMapIterator<AbstractInterface*,QList<char>* > iterAP(admittance);\r
+ QMapIterator<AbstractInterface*,QList<char>* > iterIP(inputPattern);\r
+\r
+ while (iterAP.hasNext()) {\r
+ iterAP.next();\r
+ iterIP.next();\r
+ QList<char>* ap = iterAP.value();\r
+ QList<char>* ip = iterIP.value();\r
+ int first = 0;\r
+ while ((first < lengthIP) && (ip->at(first) == 0)) first++;\r
+ while ((first < lengthAP) && (ap->at(first) == 0)) first--;\r
+ delays.append(first);\r
+ inClock.append(0);\r
+ QList<int>* delays = new QList<int>();\r
+ admittanceDelays.insert(iterAP.key(), delays);\r
+ }\r
+\r
+ QMapIterator<AbstractInterface*,QList<int>* > iterDelays(admittanceDelays);\r
+\r
+ // get the delay to apply\r
+ int maxDelay = 0;\r
+ for(int i=0;i<delays.size();i++) {\r
+ if (delays[i] > maxDelay) maxDelay = delays[i];\r
+ }\r
+ // adding the delays to IP\r
+ iterIP.toFront();\r
+ int i = 0;\r
+ while (iterIP.hasNext()) {\r
+ iterIP.next();\r
+ iterDelays.next();\r
+ QList<char>* ip = iterIP.value();\r
+ QList<int>* d = iterDelays.value();\r
+ d->append(maxDelay-delays[i]);\r
+ cout << "prependind " << qPrintable(iterIP.key()->getName()) << " with " << (maxDelay-delays[i]) << " 0" << endl;\r
+ for(int j=0;j<maxDelay-delays[i];j++) {\r
+ ip->prepend(0);\r
+ }\r
+ for(int j=0;j<delays[i];j++) {\r
+ ip->append(0);\r
+ }\r
+ i++;\r
+ }\r
+ lengthIP += maxDelay;\r
+\r
+ cout << "IP length = " << lengthIP << ", AP length = " << lengthAP << endl;\r
+ bool stop = false;\r
+ int apIndex = 0;\r
+ int ipIndex = 0;\r
+ while (!stop) {\r
+\r
+ // if AP is a valid group, search for the next valid group in IP\r
+ if (isValidDataGroup(admittance,apIndex)) {\r
+\r
+ while ((ipIndex < lengthIP) && (! isValidDataGroup(inputPattern,ipIndex))) ipIndex++;\r
+ if (ipIndex == lengthIP) {\r
+ stop = true;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ iterAP.toFront();\r
+ iterIP.toFront();\r
+ iterDelays.toFront();\r
+\r
+ if (samePatterns(inputPattern,ipIndex,admittance,apIndex)) {\r
+ while (iterAP.hasNext()) {\r
+ iterAP.next();\r
+ iterDelays.next();\r
+ QList<char>* ap = iterAP.value();\r
+ if (ap->at(apIndex) == 1) {\r
+ QList<int>* d = iterDelays.value();\r
+ d->append(0); // the 1 is at its good place, so no delay\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ cout << "diff between IP and AP at " << apIndex << endl;\r
+ // search for the next 1 in IP for every input that has a 1 in AP\r
+\r
+ while (iterAP.hasNext()) {\r
+ iterAP.next();\r
+ iterIP.next();\r
+ iterDelays.next();\r
+ QList<char>* ap = iterAP.value();\r
+ QList<char>* ip = iterIP.value();\r
+ QList<int>* d = iterDelays.value();\r
+ // case 1: 1 in IP is too late\r
+ if ((ap->at(apIndex) == 1) && (ip->at(ipIndex) == 0)) {\r
+ int delay = 1;\r
+ while ( ((ipIndex+delay) < lengthIP) && (ip->at(ipIndex+delay) == 0) ) delay++;\r
+ cout << "found a delay of " << (-delay) << " for iface " << qPrintable(iterAP.key()->getName()) << endl;\r
+ // moving the 1 to its normal pos.\r
+ ip->replace(ipIndex,1);\r
+ ip->replace(ipIndex+delay,0);\r
+ d->append(-delay);\r
+ }\r
+ // case 2: 1 in IP is too soon\r
+ else if ((ap->at(apIndex) == 0) && (ip->at(ipIndex) == 1)) {\r
+ int delay = 1;\r
+ while ( ((apIndex+delay) < lengthAP) && (ap->at(apIndex+delay) == 0) ) delay++;\r
+ cout << "found a delay of " << delay << " for iface " << qPrintable(iterAP.key()->getName()) << endl;\r
+ // search for next 0 in IP to put the 1\r
+ int k = ipIndex+delay;\r
+ while ((k < lengthIP) && (ip->at(k) == 1)) k++;\r
+ ip->replace(ipIndex,0);\r
+ ip->replace(k,1);\r
+ d->append(delay);\r
+ }\r
+ }\r
+ if (! samePatterns(inputPattern,inClock,admittance,apIndex)) {\r
+ cout << "Abnormal case while searching for delays" << endl;\r
+ }\r
+ }\r
+\r
+ apIndex++;\r
+ ipIndex++;\r
+ if ((apIndex >= lengthAP) || (ipIndex >= lengthIP)) stop = true;\r
+ }\r
+ iterDelays.toFront();\r
+ while (iterDelays.hasNext()) {\r
+ iterDelays.next();\r
+ QList<int>* d = iterDelays.value();\r
+ foreach(int v, *d) {\r
+ cout << v << " ";\r
+ }\r
+ cout << endl;\r
+ }\r
+\r
+}\r
+\r
+void FunctionalBlock::createInputPattern() throw(Exception) {\r
+ static QString fctName = "FunctionalBlock::createInputPattern())";\r
+#ifdef DEBUG_FCTNAME\r
+ cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+ \r
+ lengthIP = -1;\r
+ foreach(AbstractInterface* iface, getControlInputs()) {\r
+\r
+ ConnectedInterface* connIface = AI_TO_CON(iface);\r
+ // check if it is connected\r
+ if (connIface->getConnectedFrom() == NULL) {\r
+ throw(Exception(IFACE_NOT_CONNECTED,this));\r
+ }\r
+ // get the precursor output pattern\r
+ QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();\r
+ AbstractInputModifier* modifier = connIface->getInputModifier();\r
+ // check if the input is modified\r
+ if (modifier != NULL) {\r
+\r
+ out = modifier->getModifiedInput(out);\r
+ }\r
+\r
+ if (out->size() == 0) {\r
+ clearInputPattern();\r
+ throw(Exception(NO_IFACE_IP,this));\r
+ }\r
+ if (lengthIP == -1) {\r
+ lengthIP = out->size();\r
+ }\r
+ else {\r
+ if (out->size() < lengthIP) lengthIP = out->size();\r
+ }\r
+ \r
+ QList<char>* in = new QList<char>(*out);\r
+ foreach(char c, *in) {\r
+ cout << (int)c;\r
+ }\r
+ cout << endl; \r
+ inputPattern.insert(connIface,in); \r
+ }\r
+ // search the last valid group in IP,\r
+ while(! isValidDataGroup(inputPattern,lengthIP-1)) {\r
+ //removeDataGroup(inputPattern,lengthIP-1);\r
+ lengthIP -= 1;\r
+ }\r
+}\r
+\r
+void FunctionalBlock::createAdmittance(int nbExec) throw(Exception) {\r
+ static QString fctName = "FunctionalBlock::createAdmittance()";\r
+#ifdef DEBUG_FCTNAME\r
+ cout << "call to " << qPrintable(fctName) << endl;\r
+#endif \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
+ throw(INVALID_DELTA_CP); \r
+ }\r
+ }\r
+ }\r
+ // turn all X into 0\r
+ QMapIterator<AbstractInterface*,QList<char>* > iterA(admittance);\r
+ while (iterA.hasNext()) {\r
+ iterA.next();\r
+ QList<char>* pattern = iterA.value();\r
+ for(int i=0;i<pattern->size();i++) {\r
+ if (pattern->at(i) == -1) pattern->replace(i,0);\r
+ cout << (int)(pattern->at(i));\r
+ }\r
+ cout << endl;\r
+ } \r
+}\r
+\r
+void FunctionalBlock::checkInputPatternCompatibility() throw(Exception) {\r
+ static QString fctName = "FunctionalBlock::checkInputPatternCompatibility()";\r
+#ifdef DEBUG_FCTNAME\r
+ cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+ \r
+ // firstly, create input pattern\r
+ try {\r
+ createInputPattern();\r
+ }\r
+ catch(Exception e) {\r
+ throw(e);\r
+ }\r
+ int nbExec = createTriggers();\r
+ cout << qPrintable(name) << " will exec. " << nbExec << " times." << endl;\r
+ \r
+ try {\r
+ createAdmittance(nbExec);\r
+ }\r
+ catch(Exception e) {\r
+ cout << "cannot create admittance" << endl;\r
+ throw(e);\r
+ }\r
+ \r
+ int clock = 0; // index in IP \r
+ int i = 0; // index in AP \r
+ while ((clock < lengthIP) && (i < lengthAP)) {\r
+ \r
+ // if AP is a valid group, search for the next valid group in IP\r
+ if (isValidDataGroup(admittance,i)) {\r
+ while ((clock < lengthIP) && (! isValidDataGroup(inputPattern,clock))) clock++;\r
+ if (clock == lengthIP) {\r
+ cerr << "Abnormal case: end of IP has been reached without finding a valid group" << endl;\r
+ throw(Exception(IP_END_NULLCOL,this));\r
+ }\r
+ } \r
+ /* at that point 2 cases of compat : IP(clock) and AP(i) are equal valid group, or\r
+ are both null columns\r
+ */\r
+ if (! samePatterns(inputPattern,clock,admittance,i)) {\r
+ cout << "AP(" << i << ") and IP(" << clock << ") are not equal" << endl;\r
+ throw(Exception(IP_AP_NOTCOMPAT,this)); // IP and AP not compatible\r
+ }\r
+ clock++;\r
+ i++;\r
+ }\r
+ if (clock < lengthIP) {\r
+ throw(Exception(AP_TOO_SHORT,this));\r
+ cerr << "Abnormal case: AP is to short" << endl; \r
+ } \r
+}\r
+\r
+void FunctionalBlock::computeOutputPattern(int nbExec) throw(Exception) {\r
+ static QString fctName = "FunctionalBlock::computeOutputPattern()";\r
+#ifdef DEBUG_FCTNAME\r
+ cout << "call to " << qPrintable(fctName) << endl;\r
+#endif\r
+\r
+ clearOutputPattern();\r
+\r