+\r
+void 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
+ inputPattern[idIface] = new char[in.size()];\r
+ int i = 0;\r
+ foreach(char c, in) inputPattern[idIface][i++] = c;\r
+ idIface += 1; \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
+}\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