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

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