1 #include "FunctionalBlock.h"
\r
2 #include "ReferenceBlock.h"
\r
3 #include "GroupBlock.h"
\r
4 #include "AbstractInterface.h"
\r
5 #include "FunctionalInterface.h"
\r
6 #include "ReferenceInterface.h"
\r
7 #include "BlockParameter.h"
\r
10 FunctionalBlock::FunctionalBlock(GroupBlock *_parent, ReferenceBlock *_reference) throw(Exception) : AbstractBlock() {
\r
11 //if (! _reference->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
\r
12 //if (! _group->isGroupBlock()) throw(Exception(BLOCK_INVALID_TYPE));
\r
13 reference = _reference;
\r
15 name = reference->getName();
\r
16 consumptionPattern = NULL;
\r
18 nbConsumingPorts = 0;
\r
19 productionPattern = NULL;
\r
21 nbProducingPorts = 0;
\r
25 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
\r
27 checkedBlocks->append(this);
\r
29 foreach(BlockParameter* param, params){
\r
30 if(param->isUserParameter() && !param->isValueSet()){
\r
31 if(!blocksToConfigure->contains(param->getOwner())){
\r
32 blocksToConfigure->append(param->getOwner());
\r
36 foreach(AbstractInterface *inter, outputs){
\r
37 foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
\r
38 if(!checkedBlocks->contains(connectedInter->getOwner())){
\r
39 connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
\r
46 bool FunctionalBlock::isFunctionalBlock() {
\r
50 bool FunctionalBlock::isSourceBlock() {
\r
51 if (parent == NULL) return true;
\r
55 void FunctionalBlock::populate() {
\r
58 AbstractInterface* inter;
\r
60 // create parameters from reference block
\r
61 QList<BlockParameter*> lstParam = reference->getParameters();
\r
62 for(i=0;i<lstParam.size();i++) {
\r
63 p = lstParam.at(i)->clone();
\r
67 // create interfaces from reference block
\r
68 QList<AbstractInterface *> lstRef = reference->getInterfaces();
\r
69 // store relation between functional and reference
\r
70 QHash<AbstractInterface *, AbstractInterface *> hashIface;
\r
71 for(i=0;i<lstRef.size();i++) {
\r
73 inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));
\r
75 catch(Exception e) {
\r
76 cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;
\r
79 hashIface.insert(lstRef.at(i),inter);
\r
81 addInterface(inter);
\r
84 AbstractInterface* funCtlIface = NULL;
\r
85 AbstractInterface* funDataIface = NULL;
\r
87 for(i=0;i<lstRef.size();i++) {
\r
88 AbstractInterface* refIface = lstRef.at(i);
\r
89 if (refIface->getPurpose() == AbstractInterface::Control) {
\r
90 funCtlIface = hashIface.value(refIface);
\r
91 funDataIface = hashIface.value(refIface->getAssociatedIface());
\r
92 if (! funCtlIface->setAssociatedIface(funDataIface)) {
\r
93 cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;
\r
101 QString FunctionalBlock::getReferenceXmlFile() {
\r
102 return ((ReferenceBlock *)reference)->getXmlFile();
\r
105 QString FunctionalBlock::getReferenceHashMd5() {
\r
106 return ((ReferenceBlock *)reference)->getHashMd5();
\r
109 void FunctionalBlock::computeOutputPattern(int nbExec) {
\r
111 /* case 1: the block is a generator for which output pattern
\r
112 must be computed for a nbExec following executions
\r
116 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
117 QList<char> pattern;
\r
118 for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();
\r
119 iface->setOutputPattern(pattern);
\r
123 // initialize consumption and production patterns
\r
124 initConsumptionPattern();
\r
125 initProductionPattern();
\r
127 // collect the input patterns for each input
\r
128 char** inputPattern = NULL;
\r
130 inputPattern = new char*[nbConsumingPorts];
\r
132 foreach(AbstractInterface* iface, getControlInputs()) {
\r
133 QList<char> in = iface->getConnectedFrom()->getOutputPattern();
\r
134 if (minLen == -1) {
\r
135 minLen = in.size();
\r
138 if (in.size() < minLen) minLen = in.size();
\r
140 inputPattern[idIface] = new char[in.size()];
\r
142 foreach(char c, in) inputPattern[idIface][i++] = c;
\r
145 // initialize the output pattern
\r
146 char** outputPattern = NULL;
\r
147 outputPattern = new char*[nbProducingPorts];
\r
150 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
151 lengthOP = minLen+iface->getProductionPattern().size();
\r
152 outputPattern[idIface] = new char[lengthOP];
\r
153 memset(outputPattern[idIface],0,lengthOP);
\r
159 // search for the beginning of the first execution.
\r
160 while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;
\r
162 while (clock < minLen) {
\r
163 // initialize counters for current execution.
\r
164 int p = 0; // index in production pattern
\r
165 int o = 0; // clock+o will give the clock cycle of each output group
\r
166 int cip = 0; // clock+cip give the clock cycle of an input group
\r
167 int ccp = 0; // ccp give a column in the consumptio pattern
\r
168 int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP
\r
169 int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP
\r
170 bool cannotCompleteExec = false;
\r
171 for(int m=0;m<productionCounter.size();m++) {
\r
172 // search for the first production in PP
\r
173 while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {
\r
177 int gap = 0; // count the number of extra null columns
\r
178 // search for PC(m) valid input group in IP
\r
179 while (nip < productionCounter.at(m)) {
\r
180 if (clock+cip < minLen) {
\r
181 if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;
\r
186 cannotCompleteExec = true;
\r
191 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
193 // search for PC(m) valid input group in IP
\r
194 while (ncp < productionCounter.at(m)) {
\r
195 if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;
\r
199 o += gap; // to take into acocunt of extra null columns
\r
200 combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);
\r
205 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
207 // current exec. taken into accunt
\r
210 // search for the next exec.
\r
213 while ((clock < minLen) && (nip < delta)) {
\r
214 if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;
\r
215 if (nip < delta) clock += 1;
\r
218 // find the last valid output data group
\r
219 while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;
\r
221 // copy back outputPattern info each interface
\r
223 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
224 QList<char> pattern;
\r
225 for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);
\r
226 iface->setOutputPattern(pattern);
\r
230 // clear inputPattern and outputPattern
\r
231 for(int i=0;i<nbConsumingPorts; i++) {
\r
232 delete [] inputPattern[i];
\r
234 delete [] inputPattern;
\r
235 for(int i=0;i<nbProducingPorts; i++) {
\r
236 delete [] outputPattern[i];
\r
238 delete [] outputPattern;
\r
242 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {
\r
244 for(int i=0;i<nbPorts;i++) {
\r
245 if (pattern[i][clock] == 1) return true;
\r
250 void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {
\r
252 for (int i=0;i<nbCols;i++) {
\r
253 for(int j=0;j<nbPorts;j++) {
\r
254 patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];
\r
260 void FunctionalBlock::clearConsumptionPattern() {
\r
261 if (consumptionPattern == NULL) return;
\r
263 for(int i=0;i<nbConsumingPorts; i++) {
\r
264 delete [] consumptionPattern[i];
\r
266 delete [] consumptionPattern;
\r
269 void FunctionalBlock::clearProductionPattern() {
\r
270 if (productionPattern == NULL) return;
\r
271 for(int i=0;i<nbProducingPorts;i++) {
\r
272 delete [] productionPattern[i];
\r
274 delete [] productionPattern;
\r
277 void FunctionalBlock::initConsumptionPattern() {
\r
278 if (consumptionPattern != NULL) clearConsumptionPattern();
\r
280 nbConsumingPorts = getControlInputs().size();
\r
282 consumptionPattern = new char*[nbConsumingPorts];
\r
283 foreach(AbstractInterface* iface, getControlInputs()) {
\r
285 QList<char> in = iface->getConsumptionPattern();
\r
286 lengthCP = in.size(); // normally, all inputs have the same lenght for CP
\r
287 consumptionPattern[idIface] = new char[lengthCP];
\r
289 foreach(char c, in) consumptionPattern[idIface][i++] = c;
\r
294 void FunctionalBlock::initProductionPattern() {
\r
295 if (productionPattern != NULL) clearProductionPattern();
\r
297 nbProducingPorts = getControlOutputs().size();
\r
299 productionPattern = new char*[nbProducingPorts];
\r
300 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
302 QList<char> in = iface->getProductionPattern();
\r
303 lengthPP = in.size(); // normally, all inputs have the same lenght for PP
\r
304 productionPattern[idIface] = new char[lengthPP];
\r
306 foreach(char c, in) productionPattern[idIface][i++] = c;
\r