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
22 if (reference->getImplementations().isEmpty()) {
\r
23 implementation = NULL;
\r
24 cout << "block has no implementation" << endl;
\r
27 implementation = reference->getImplementations().at(0);
\r
32 void FunctionalBlock::parametersValidation(QList<AbstractBlock*>* checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
\r
34 checkedBlocks->append(this);
\r
36 foreach(BlockParameter* param, params){
\r
37 if(param->isUserParameter() && !param->isValueSet()){
\r
38 if(!blocksToConfigure->contains(param->getOwner())){
\r
39 blocksToConfigure->append(param->getOwner());
\r
43 foreach(AbstractInterface *inter, outputs){
\r
44 foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
\r
45 if(!checkedBlocks->contains(connectedInter->getOwner())){
\r
46 connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
\r
53 bool FunctionalBlock::isFunctionalBlock() {
\r
57 bool FunctionalBlock::isSourceBlock() {
\r
58 if (parent == NULL) return true;
\r
62 void FunctionalBlock::populate() {
\r
65 AbstractInterface* inter;
\r
67 // create parameters from reference block
\r
68 QList<BlockParameter*> lstParam = reference->getParameters();
\r
69 for(i=0;i<lstParam.size();i++) {
\r
70 p = lstParam.at(i)->clone();
\r
74 // create interfaces from reference block
\r
75 QList<AbstractInterface *> lstRef = reference->getInterfaces();
\r
76 // store relation between functional and reference
\r
77 QHash<AbstractInterface *, AbstractInterface *> hashIface;
\r
78 for(i=0;i<lstRef.size();i++) {
\r
80 inter = new FunctionalInterface(this, AI_TO_REF(lstRef.at(i)));
\r
82 catch(Exception e) {
\r
83 cerr << "Abnormal case: " << qPrintable(e.getDefaultMessage()) << endl << "Aborting execution." << endl;
\r
86 hashIface.insert(lstRef.at(i),inter);
\r
88 addInterface(inter);
\r
91 AbstractInterface* funCtlIface = NULL;
\r
92 AbstractInterface* funDataIface = NULL;
\r
94 for(i=0;i<lstRef.size();i++) {
\r
95 AbstractInterface* refIface = lstRef.at(i);
\r
96 if (refIface->getPurpose() == AbstractInterface::Control) {
\r
97 funCtlIface = hashIface.value(refIface);
\r
98 funDataIface = hashIface.value(refIface->getAssociatedIface());
\r
99 if (! funCtlIface->setAssociatedIface(funDataIface)) {
\r
100 cerr << "Abnormal case when associating a control interface to data" << endl << "Aborting execution." << endl;
\r
108 QString FunctionalBlock::getReferenceXmlFile() {
\r
109 return ((ReferenceBlock *)reference)->getXmlFile();
\r
112 QString FunctionalBlock::getReferenceHashMd5() {
\r
113 return ((ReferenceBlock *)reference)->getHashMd5();
\r
116 bool FunctionalBlock::createPatterns() {
\r
117 evaluator = new ArithmeticEvaluator();
\r
119 ok = ok & createDelta();
\r
120 if (ok) ok = ok & createConsumptionPattern();
\r
121 if (ok) ok = ok & createProductionCounter();
\r
122 if (ok) ok = ok & createProductionPattern();
\r
127 bool FunctionalBlock::createDelta() {
\r
128 QString delta = implementation->getDelta();
\r
129 cout << "delta for " << qPrintable(name) << " = " << qPrintable(delta) << endl;
\r
131 // look for parameter names
\r
132 QHash<QString,double> vars;
\r
133 QRegularExpression re("[$][a-zA-Z0-9_]+");
\r
134 QRegularExpressionMatchIterator matcher = re.globalMatch(delta);
\r
135 while(matcher.hasNext()) {
\r
136 QRegularExpressionMatch m = matcher.next();
\r
137 QString var = m.captured(0);
\r
138 cout << qPrintable(var) << endl;
\r
139 vars.insert(var,0.0);
\r
141 QHashIterator<QString,double> iterV(vars);
\r
142 while (iterV.hasNext()) {
\r
144 QString var = iterV.key();
\r
145 QString paramName = var.remove(0,1);
\r
146 BlockParameter* param = reference->getParameterFromName(paramName);
\r
147 cout << "param = " << qPrintable(param->getStringValue()) << endl;
\r
148 if (param == NULL) {
\r
149 cerr << "found an unknown parameter in delta"<< endl;
\r
153 int val = param->getIntValue(&ok);
\r
154 vars.insert(var,(double)val);
\r
156 cout << "set expr " << endl;
\r
157 evaluator->setExpression(delta);
\r
158 cout << "set vars " << endl;
\r
159 evaluator->setVariablesValue(vars);
\r
160 double result = evaluator->evaluate();
\r
161 cout << "delta = " << result << endl;
\r
166 bool FunctionalBlock::createConsumptionPattern() {
\r
170 bool FunctionalBlock::createProductionPattern() {
\r
174 bool FunctionalBlock::createProductionCounter() {
\r
178 bool FunctionalBlock::computeOutputPattern(int nbExec) {
\r
180 /* case 1: the block is a generator for which output pattern
\r
181 must be computed for a nbExec following executions
\r
185 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
186 QList<char> pattern;
\r
187 for(int i=0;i<nbExec;i++) pattern += iface->getProductionPattern();
\r
188 iface->setOutputPattern(pattern);
\r
192 // initialize consumption and production patterns
\r
193 initConsumptionPattern();
\r
194 initProductionPattern();
\r
196 // collect the input patterns for each input
\r
197 char** inputPattern = NULL;
\r
199 inputPattern = new char*[nbConsumingPorts];
\r
201 foreach(AbstractInterface* iface, getControlInputs()) {
\r
202 QList<char> in = iface->getConnectedFrom()->getOutputPattern();
\r
203 if (minLen == -1) {
\r
204 minLen = in.size();
\r
207 if (in.size() < minLen) minLen = in.size();
\r
209 if (in.size() > 0) {
\r
210 inputPattern[idIface] = new char[in.size()];
\r
212 foreach(char c, in) inputPattern[idIface][i++] = c;
\r
215 inputPattern[idIface] = NULL;
\r
219 // if some patterns are not available, ens now, returning false
\r
221 for(int i=0;i<nbConsumingPorts; i++) {
\r
222 if (inputPattern[i] != NULL) delete [] inputPattern[i];
\r
224 delete [] inputPattern;
\r
227 // initialize the output pattern
\r
228 char** outputPattern = NULL;
\r
229 outputPattern = new char*[nbProducingPorts];
\r
232 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
233 lengthOP = minLen+iface->getProductionPattern().size();
\r
234 outputPattern[idIface] = new char[lengthOP];
\r
235 memset(outputPattern[idIface],0,lengthOP);
\r
241 // search for the beginning of the first execution.
\r
242 while (! isValidDataGroup(inputPattern,nbConsumingPorts,clock)) clock++;
\r
244 while (clock < minLen) {
\r
245 // initialize counters for current execution.
\r
246 int p = 0; // index in production pattern
\r
247 int o = 0; // clock+o will give the clock cycle of each output group
\r
248 int cip = 0; // clock+cip give the clock cycle of an input group
\r
249 int ccp = 0; // ccp give a column in the consumptio pattern
\r
250 int nip = 0; // number of input data groups already consumed during the current execution, used while exploring IP
\r
251 int ncp = 0; // number of input data groups already consumed during the current execution, used while exploring CP
\r
252 bool cannotCompleteExec = false;
\r
253 for(int m=0;m<productionCounter.size();m++) {
\r
254 // search for the first production in PP
\r
255 while (!isValidDataGroup(productionPattern,nbProducingPorts,p)) {
\r
259 int gap = 0; // count the number of extra null columns
\r
260 // search for PC(m) valid input group in IP
\r
261 while (nip < productionCounter.at(m)) {
\r
262 if (clock+cip < minLen) {
\r
263 if (isValidDataGroup(inputPattern,nbConsumingPorts,clock+cip)) nip += 1;
\r
268 cannotCompleteExec = true;
\r
273 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
275 // search for PC(m) valid input group in IP
\r
276 while (ncp < productionCounter.at(m)) {
\r
277 if (isValidDataGroup(consumptionPattern,nbConsumingPorts,ccp)) cip += 1;
\r
281 o += gap; // to take into acocunt of extra null columns
\r
282 combinePatterns(productionPattern,p,outputPattern,clock+o,1,nbProducingPorts);
\r
287 if (cannotCompleteExec) break; // no need to go further since the next search of input data group will lead to go outside inputPattern
\r
289 // current exec. taken into accunt
\r
292 // search for the next exec.
\r
295 while ((clock < minLen) && (nip < delta)) {
\r
296 if (isValidDataGroup(inputPattern,nbConsumingPorts,clock)) nip += 1;
\r
297 if (nip < delta) clock += 1;
\r
300 // find the last valid output data group
\r
301 while(! isValidDataGroup(outputPattern,nbProducingPorts,lengthOP-1)) lengthOP -= 1;
\r
303 // copy back outputPattern info each interface
\r
305 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
306 QList<char> pattern;
\r
307 for(int i=0;i<lengthOP;i++) pattern.append(outputPattern[idIface][i]);
\r
308 iface->setOutputPattern(pattern);
\r
312 // clear inputPattern and outputPattern
\r
313 for(int i=0;i<nbConsumingPorts; i++) {
\r
314 delete [] inputPattern[i];
\r
316 delete [] inputPattern;
\r
317 for(int i=0;i<nbProducingPorts; i++) {
\r
318 delete [] outputPattern[i];
\r
320 delete [] outputPattern;
\r
325 bool FunctionalBlock::isValidDataGroup(char** pattern, int nbPorts, int clock) {
\r
327 for(int i=0;i<nbPorts;i++) {
\r
328 if (pattern[i][clock] == 1) return true;
\r
333 void FunctionalBlock::combinePatterns(char** patternSrc, int srcCol, char** patternDest, int destCol, int nbCols, int nbPorts ) {
\r
335 for (int i=0;i<nbCols;i++) {
\r
336 for(int j=0;j<nbPorts;j++) {
\r
337 patternDest[j][destCol+i] = patternDest[j][destCol+i] | patternSrc[j][srcCol+i];
\r
343 void FunctionalBlock::clearConsumptionPattern() {
\r
344 if (consumptionPattern == NULL) return;
\r
346 for(int i=0;i<nbConsumingPorts; i++) {
\r
347 delete [] consumptionPattern[i];
\r
349 delete [] consumptionPattern;
\r
352 void FunctionalBlock::clearProductionPattern() {
\r
353 if (productionPattern == NULL) return;
\r
354 for(int i=0;i<nbProducingPorts;i++) {
\r
355 delete [] productionPattern[i];
\r
357 delete [] productionPattern;
\r
360 void FunctionalBlock::initConsumptionPattern() {
\r
361 if (consumptionPattern != NULL) clearConsumptionPattern();
\r
363 nbConsumingPorts = getControlInputs().size();
\r
365 consumptionPattern = new char*[nbConsumingPorts];
\r
366 foreach(AbstractInterface* iface, getControlInputs()) {
\r
368 QList<char> in = iface->getConsumptionPattern();
\r
369 lengthCP = in.size(); // normally, all inputs have the same lenght for CP
\r
370 consumptionPattern[idIface] = new char[lengthCP];
\r
372 foreach(char c, in) consumptionPattern[idIface][i++] = c;
\r
377 void FunctionalBlock::initProductionPattern() {
\r
378 if (productionPattern != NULL) clearProductionPattern();
\r
380 nbProducingPorts = getControlOutputs().size();
\r
382 productionPattern = new char*[nbProducingPorts];
\r
383 foreach(AbstractInterface* iface, getControlOutputs()) {
\r
385 QList<char> in = iface->getProductionPattern();
\r
386 lengthPP = in.size(); // normally, all inputs have the same lenght for PP
\r
387 productionPattern[idIface] = new char[lengthPP];
\r
389 foreach(char c, in) productionPattern[idIface][i++] = c;
\r