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

Private GIT Repository
add clk/rst to groups
[blast.git] / GroupBlock.cpp
1 #include "GroupBlock.h"
2 #include "BlockParameterGeneric.h"
3 #include "AbstractInterface.h"
4 #include "ConnectedInterface.h"
5 #include "GroupInterface.h"
6 #include "string.h"
7 #include <sstream>
8
9 int GroupBlock::counter = 1;
10
11 GroupBlock::GroupBlock(GroupBlock *_parent) throw(Exception) :  AbstractBlock() {
12
13   // force topGroup to false if this group has a parent
14   if (_parent != NULL) {
15     topGroup = false;
16     name = QString("sub_group")+"_"+QString::number(counter++);
17   }
18   else {
19     topGroup = true;
20     name = QString("top_group");
21     // creating external clk/rst interfaces
22     GroupInterface* clk = new GroupInterface(this,"ext_clk", AbstractInterface::Input, AbstractInterface::Clock);
23     GroupInterface* rst = new GroupInterface(this,"ext_reset", AbstractInterface::Input, AbstractInterface::Reset);
24     addInterface(clk);
25     addInterface(rst);
26     // creating clkrstgen block : done in Dispatcher since this has no access to library
27   }
28   parent = _parent;
29   if (parent != NULL) {
30     // adding this to the child blocks of parent
31     AB_TO_GRP(parent)->addBlock(this);
32   }
33 }
34
35 GroupBlock::~GroupBlock() {
36   foreach(AbstractBlock* block, blocks) {
37     delete block;
38   }
39 }
40
41 bool GroupBlock::isGroupBlock() {
42   return true;
43 }
44
45 bool GroupBlock::isTopGroupBlock() {
46   return topGroup;
47 }
48
49 void GroupBlock::setParent(AbstractBlock *_parent) {
50   parent = _parent;
51   if (parent != NULL) {
52     topGroup = false;
53   }
54 }
55
56 void GroupBlock::removeAllBlocks() {
57   foreach(AbstractBlock* block, blocks) {
58     if (block->isGroupBlock()) {
59       GroupBlock* group = AB_TO_GRP(block);
60       group->removeAllBlocks();
61     }
62     removeBlock(block);
63   }
64 }
65
66 void GroupBlock::removeBlock(AbstractBlock* block) {
67   /* CAUTION: no check is done if the block has connected interface
68      or not. Thus, they must be deleted elsewhere.
69   */
70   blocks.removeAll(block);
71   delete block;
72 }
73
74 AbstractBlock *GroupBlock::getFunctionalBlockByName(QString name) {
75   foreach(AbstractBlock* block, blocks) {
76     if (block->isFunctionalBlock()) {
77       if (block->getName() == name) return block;
78     }
79   }
80   return NULL;
81 }
82
83 void GroupBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
84
85   /*
86   checkedBlocks->append(this);
87
88   foreach(BlockParameter* param, params){
89     if(param->isUserParameter() && !param->isValueSet()){
90       if(!blocksToConfigure->contains(param->getOwner())){
91         blocksToConfigure->append(param->getOwner());
92       }
93     }
94   }
95   foreach(AbstractInterface *inter, outputs){
96     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
97       if(!checkedBlocks->contains(connectedInter->getOwner())){
98         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
99       }
100     }
101   }
102   */
103 }
104
105 void GroupBlock::addGenericParameter(QString name, QString type, QString value) {
106   BlockParameter* param = new BlockParameterGeneric(this, name, type, value);
107   params.append(param);
108 }
109
110 void GroupBlock::removeGenericParameter(QString name) {
111   BlockParameter* p = getParameterFromName(name);
112   if (p != NULL) params.removeAll(p);
113 }
114
115 void GroupBlock::createInputPattern() {
116   foreach(AbstractInterface* iface, getControlInputs()) {
117     ConnectedInterface* connIface = AI_TO_CON(iface);
118     QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
119     connIface->setOutputPattern(pattern);
120   }
121 }
122
123 void GroupBlock::computeAdmittanceDelays() throw(Exception) {
124   throw(Exception(INVALID_GROUPBLOCK_USE));
125 }
126
127 void GroupBlock::checkInputPatternCompatibility()  throw(Exception){
128   throw(Exception(INVALID_GROUPBLOCK_USE));
129 }
130
131
132 void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) {
133
134   static QString fctName = "GroupBlock::computeOutputPattern()";
135 #ifdef DEBUG_FCTNAME
136   cout << "call to " << qPrintable(fctName) << endl;
137 #endif
138
139   cout << "computing output pattern of group " << qPrintable(name) << endl;
140   
141   bool canCompute = false;
142   // get the input pattern on each inputs
143   createInputPattern();
144   
145   cout << "Input pattern OK" << endl;
146   // find blocks that are connected to that inputs and generators
147   QList<AbstractBlock*> fifo;
148   foreach(AbstractBlock* block, blocks) {
149
150     bool addIt = false;
151     // if a block is a generator and has control outputs, add it
152     if (block->isGeneratorBlock()) {
153       if (block->getControlOutputs().size() > 0) addIt = true;
154     }
155     else {
156       // if the block has all its connected inputs that are connected to an intput of the group, add it too
157       addIt = true;
158       foreach(AbstractInterface* iface, block->getControlInputs()) {
159         //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
160         ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
161         //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
162         
163         if (connFrom == NULL) {
164           addIt = false;
165           break;
166         }
167         else if (connFrom->getOwner() != this) {
168           addIt = false;
169           break;
170         }
171       }
172     }
173     if (addIt) {
174       cout << "adding " << qPrintable(block->getName()) << " to initialize the FIFO" << endl;
175       block->setTraversalLevel(0); // level 0 = first blocks to be evaluated
176       fifo.append(block);
177     }
178   }
179   
180   while (!fifo.isEmpty()) {
181     AbstractBlock* block = fifo.takeFirst();
182     
183     if (block->getPatternComputed()) continue; // block has already been processed
184
185     cout << "computing compat and output for " << qPrintable(block->getName()) << endl;
186     
187
188     try {
189       block->checkInputPatternCompatibility();
190     }
191     catch(Exception e) {      
192       cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl;
193       throw(e);
194     }   
195     
196     try {
197       block->computeOutputPattern();
198     }
199     catch(Exception e) {
200       cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
201       throw(e);
202     }
203     canCompute = true;
204     block->setPatternComputed(true);
205     /* add other blocks connected from block to the fifo but only if
206        all their connected inputs are connected to blocks that have
207        a traversalLevel >=0
208      */
209     foreach(AbstractInterface* iface, block->getControlOutputs()) {
210       ConnectedInterface* conn = (ConnectedInterface*)iface;
211       foreach(ConnectedInterface* connTo, conn->getConnectedTo()) {
212
213         AbstractBlock* block1 = connTo->getOwner();
214         cout << "testing if " << qPrintable(block1->getName()) << " has all connected inputs connected to already processed blocks" << endl;
215         bool addIt = true;
216         int maxLevel = 0;
217
218         foreach(AbstractInterface* iface, block1->getControlInputs()) {
219           //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
220           ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
221           //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
222
223           if ((connFrom != NULL) && (connFrom->getOwner()->getPatternComputed() == false)) {
224             addIt = false;
225             break;
226           }
227           else {
228             if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel();
229           }
230         }
231
232         if (addIt) {
233           cout << "adding " << qPrintable(block1->getName()) << " to the FIFO" << endl;
234           block1->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated
235           fifo.append(block1);
236         }
237       }
238     }
239   }
240
241   if (canCompute) {
242     foreach(AbstractInterface* iface, getControlOutputs()) {
243       ConnectedInterface* connIface = AI_TO_CON(iface);
244       QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
245       connIface->setOutputPattern(pattern);
246     }
247     setPatternComputed(true);
248   }
249 }
250
251 void GroupBlock::generateVHDL(const QString& path) throw(Exception) {
252
253   QString coreFile = "";
254
255   coreFile = path;
256   coreFile.append(normalizeName(name));
257   coreFile.append(".vhd");
258
259   QFile vhdlCore(coreFile);
260
261   if (!vhdlCore.open(QIODevice::WriteOnly)) {
262     throw(Exception(VHDLFILE_NOACCESS));
263   }
264
265   QTextStream outCore(&vhdlCore);
266
267   try {
268     generateComments(outCore);
269     generateLibraries(outCore);
270     generateEntity(outCore);
271     generateArchitecture(outCore);
272   }
273   catch(Exception err) {
274     throw(err);
275   }
276
277   vhdlCore.close();
278 }
279
280
281 void GroupBlock::generateComments(QTextStream& out) throw(Exception) {
282   out << " -- VHDL generated automatically for " << name << " --" << endl << endl;
283 }
284
285 void GroupBlock::generateLibraries(QTextStream& out) throw(Exception) {
286
287   out << "library IEEE;" << endl;
288   out << "use IEEE.STD_LOGIC_1164.all;" << endl;
289   out << "use IEEE.numeric_std.all;" << endl;
290
291 }
292
293 void GroupBlock::generateEntity(QTextStream& out) throw(Exception) {
294
295   int i;
296
297   out << "entity " << name << " is " << endl;
298
299   QList<BlockParameter*> listGenerics = getGenericParameters();
300   QList<AbstractInterface*> listInputs = getInputs();
301   QList<AbstractInterface*> listOutputs = getOutputs();
302   QList<AbstractInterface*> listBidirs = getBidirs();
303
304   if (!listGenerics.isEmpty()) {
305     out << "  generic (" << endl;
306     for(i=0;i<listGenerics.size()-1;i++) {
307       out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl;
308     }
309     out << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl;
310     out << "    );" << endl;
311   }
312
313   out << "  port (" << endl;
314
315   // Generation of the clk & rst signals
316   out << "    -- clk/rst" << endl;
317   foreach(AbstractInterface* iface, listInputs) {
318     if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) {
319       out << "    " << iface->getName() << " : in std_logic;" << endl;
320     }
321   }
322
323   int count = 0;
324   foreach(AbstractInterface* iface, getInterfaces()) {
325     if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++;
326   }
327   // Generation of the data/control signals
328
329   int flag = 0;
330   bool first = true;
331
332   foreach(AbstractInterface* iface, listInputs) {
333     if(iface->getPurpose() == AbstractInterface::Data) {
334       if (first) {
335         out << "    -- input data ports" << endl;
336         first = false;
337       }
338       count--;
339       if (count == 0) flag = AbstractInterface::NoComma;
340       out << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
341     }
342   }
343   first = true;
344   foreach(AbstractInterface* iface, listInputs) {
345     if(iface->getPurpose() == AbstractInterface::Control) {
346       if (first) {
347         out << "    -- input control ports" << endl;
348         first = false;
349       }
350       count--;
351       if (count == 0) flag = AbstractInterface::NoComma;
352       out << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
353     }
354   }
355   first = true;
356   foreach(AbstractInterface* iface, listOutputs) {
357     if(iface->getPurpose() == AbstractInterface::Data) {
358       if (first) {
359         out << "    -- output data ports" << endl;
360         first = false;
361       }
362       count--;
363       if (count == 0) flag = AbstractInterface::NoComma;
364       out << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
365     }
366   }
367   first = true;
368   foreach(AbstractInterface* iface, listOutputs) {
369     if(iface->getPurpose() == AbstractInterface::Control) {
370       if (first) {
371         out << "    -- output control ports" << endl;
372         first = false;
373       }
374       count--;
375       if (count == 0) flag = AbstractInterface::NoComma;
376       out << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
377     }
378   }
379   first = true;
380   foreach(AbstractInterface* iface, listBidirs) {
381     if(iface->getPurpose() == AbstractInterface::Data) {
382       if (first) {
383         out << "    -- bidirs data ports" << endl;
384         first = false;
385       }
386       count--;
387       if (count == 0) flag = AbstractInterface::NoComma;
388       out << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
389     }
390   }
391   out << "    );" << endl << endl;
392   out << "end " << name << ";" << endl << endl;
393
394 }
395
396 void GroupBlock::generateArchitecture(QTextStream& out) throw(Exception) {
397
398 }
399