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

Private GIT Repository
d3ff0ed715487de28fae80acf7cfb52e6db27c48
[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 #include "Parameters.h"
9 #include "DelayInputModifier.h"
10
11 int GroupBlock::counter = 1;
12
13 GroupBlock::GroupBlock(Graph *_graph, GroupBlock *_parent, bool createIfaces) throw(Exception) :  AbstractBlock(_graph) {
14
15   parent = _parent;
16   GroupInterface* clk = NULL;
17   GroupInterface* rst = NULL;
18   
19   // force topGroup to false if this group has a parent
20   if (parent != NULL) {
21     topGroup = false;
22     name = QString("sub_group")+"_"+QString::number(counter++);
23   }
24   else {
25     topGroup = true;
26     name = QString("top_group");
27     // creating external clk/rst interfaces
28   }
29
30   if (createIfaces) {
31     if (topGroup) {
32       clk = new GroupInterface(this,"ext_clk_0", AbstractInterface::Input, AbstractInterface::Clock);
33       rst = new GroupInterface(this,"ext_reset_0", AbstractInterface::Input, AbstractInterface::Reset);
34       addInterface(clk);
35       addInterface(rst);
36     }
37     else {
38       // get all clock and reset from parent
39       QList<AbstractInterface*> lstClk = parent->getInterfaces(AbstractInterface::Input, AbstractInterface::Clock);
40       QList<AbstractInterface*> lstRst = parent->getInterfaces(AbstractInterface::Input, AbstractInterface::Reset);
41       foreach(AbstractInterface* iface, lstClk) {
42         clk = new GroupInterface(this,iface->getName(),AbstractInterface::Input, AbstractInterface::Clock);
43         addInterface(clk);
44       }
45       foreach(AbstractInterface* iface, lstRst) {
46         rst = new GroupInterface(this,iface->getName(),AbstractInterface::Input, AbstractInterface::Reset);
47         addInterface(rst);
48       }
49     }
50   }
51 }
52
53 GroupBlock::~GroupBlock() {
54   foreach(AbstractBlock* block, blocks) {
55     delete block;
56   }
57 }
58
59 bool GroupBlock::isGroupBlock() {
60   return true;
61 }
62
63 bool GroupBlock::isTopGroupBlock() {
64   return topGroup;
65 }
66
67 void GroupBlock::setParent(AbstractBlock *_parent) {
68   parent = _parent;
69   if (parent != NULL) {
70     topGroup = false;
71   }
72 }
73
74 void GroupBlock::removeAllBlocks() {
75   foreach(AbstractBlock* block, blocks) {
76     if (block->isGroupBlock()) {
77       GroupBlock* group = AB_TO_GRP(block);
78       group->removeAllBlocks();
79     }
80     removeBlock(block);
81   }
82 }
83
84 void GroupBlock::removeBlock(AbstractBlock* block) {
85   /* CAUTION: no check is done if the block has connected interface
86      or not. Thus, they must be deleted elsewhere.
87   */
88   blocks.removeAll(block);
89   delete block;
90 }
91
92 AbstractBlock *GroupBlock::getFunctionalBlockByName(QString name) {
93   foreach(AbstractBlock* block, blocks) {
94     if (block->isFunctionalBlock()) {
95       if (block->getName() == name) return block;
96     }
97   }
98   return NULL;
99 }
100
101 void GroupBlock::parametersValidation(QList<AbstractBlock *> *checkedBlocks, QList<AbstractBlock *> *blocksToConfigure) {
102
103   /*
104   checkedBlocks->append(this);
105
106   foreach(BlockParameter* param, params){
107     if(param->isUserParameter() && !param->isValueSet()){
108       if(!blocksToConfigure->contains(param->getOwner())){
109         blocksToConfigure->append(param->getOwner());
110       }
111     }
112   }
113   foreach(AbstractInterface *inter, outputs){
114     foreach(AbstractInterface *connectedInter, inter->getConnectedTo()){
115       if(!checkedBlocks->contains(connectedInter->getOwner())){
116         connectedInter->getOwner()->parametersValidation(checkedBlocks, blocksToConfigure);
117       }
118     }
119   }
120   */
121 }
122
123 void GroupBlock::addGenericParameter(QString name, QString type, QString value) {
124   BlockParameter* param = new BlockParameterGeneric(this, name, type, value);
125   params.append(param);
126 }
127
128 void GroupBlock::removeGenericParameter(QString name) {
129   BlockParameter* p = getParameterFromName(name);
130   if (p != NULL) params.removeAll(p);
131 }
132
133 void GroupBlock::createInputPattern() {
134   foreach(AbstractInterface* iface, getControlInputs()) {
135     ConnectedInterface* connIface = AI_TO_CON(iface);
136     QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
137     connIface->setOutputPattern(pattern);
138   }
139 }
140
141 void GroupBlock::computeAdmittanceDelays() throw(Exception) {
142   throw(Exception(INVALID_GROUPBLOCK_USE,this));
143 }
144
145 void GroupBlock::checkInputPatternCompatibility()  throw(Exception){
146   throw(Exception(INVALID_GROUPBLOCK_USE,this));
147 }
148
149
150 void GroupBlock::computeOutputPattern(int nbExec) throw(Exception) {
151
152   static QString fctName = "GroupBlock::computeOutputPattern()";
153 #ifdef DEBUG_FCTNAME
154   cout << "call to " << qPrintable(fctName) << endl;
155 #endif
156
157   cout << "computing output pattern of group " << qPrintable(name) << endl;
158   
159   bool canCompute = false;
160   // get the input pattern on each inputs
161   createInputPattern();
162   
163   cout << "Input pattern OK" << endl;
164   // find blocks that are connected to that inputs and generators
165   QList<AbstractBlock*> fifo;
166   foreach(AbstractBlock* block, blocks) {
167
168     bool addIt = false;
169     // if a block is a generator and has control outputs, add it
170     if (block->isSourceBlock()) {
171       if (block->getControlOutputs().size() > 0) addIt = true;
172     }
173     else {
174       // if the block has all its connected control inputs that are connected to an intput of the group, add it too
175       if (block->getControlInputs().size() > 0) {
176         addIt = true;
177         foreach(AbstractInterface* iface, block->getControlInputs()) {
178           //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
179           ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
180           //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
181
182           if (connFrom == NULL) {
183             addIt = false;
184             break;
185           }
186           else if (connFrom->getOwner() != this) {
187             addIt = false;
188             break;
189           }
190         }
191       }
192     }
193     if (addIt) {
194       cout << "adding " << qPrintable(block->getName()) << " to initialize the FIFO" << endl;
195       block->setTraversalLevel(0); // level 0 = first blocks to be evaluated
196       fifo.append(block);
197     }
198   }
199   
200   while (!fifo.isEmpty()) {
201     AbstractBlock* block = fifo.takeFirst();
202     
203     if (block->getOutputPatternComputed()) continue; // block has already been processed    
204
205     try {
206       cout << "computing compatibility of " << qPrintable(block->getName()) << endl;
207       block->checkInputPatternCompatibility();
208     }
209     catch(Exception e) {      
210       cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl;
211       throw(e);
212     }   
213     
214     try {
215       cout << "computing output of " << qPrintable(block->getName()) << endl;
216       block->computeOutputPattern();
217     }
218     catch(Exception e) {
219       cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
220       throw(e);
221     }
222     canCompute = true;
223
224     /* add other blocks connected from block to the fifo but only if
225        all their connected inputs are connected to blocks that have
226        a traversalLevel >=0
227      */
228     foreach(AbstractInterface* iface, block->getControlOutputs()) {
229       ConnectedInterface* conn = (ConnectedInterface*)iface;
230       foreach(ConnectedInterface* connTo, conn->getConnectedTo()) {
231
232         AbstractBlock* blockTo = connTo->getOwner();
233         // do sthg only if blockTo is not this group block
234         if (blockTo != this) {
235           cout << "testing if " << qPrintable(blockTo->getName()) << " has all connected inputs connected to already processed blocks" << endl;
236           bool addIt = true;
237           int maxLevel = 0;
238
239           foreach(AbstractInterface* iface, blockTo->getControlInputs()) {
240             cout << qPrintable(iface->getName()) << "/" << qPrintable(iface->getOwner()->getName()) << " connected from ";
241             ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
242             cout << qPrintable(connFrom->getName()) << "/" << qPrintable(connFrom->getOwner()->getName()) << endl;
243
244             if ((connFrom != NULL) && (connFrom->getOwner()->getOutputPatternComputed() == false)) {
245               addIt = false;
246               break;
247             }
248             else {
249               if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel();
250             }
251           }
252
253           if (addIt) {
254             cout << "adding " << qPrintable(blockTo->getName()) << " to the FIFO" << endl;
255             blockTo->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated
256             fifo.append(blockTo);
257           }
258         }
259       }
260     }
261   }
262
263   if (canCompute) {
264     foreach(AbstractInterface* iface, getControlOutputs()) {
265       ConnectedInterface* connIface = AI_TO_CON(iface);
266       QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
267       connIface->setOutputPattern(pattern);
268     }
269     setOutputPatternComputed(true);
270   }
271 }
272
273 QList<QString> GroupBlock::getExternalResources() {
274
275   QList<QString> list;
276   foreach(AbstractBlock* block, blocks) {
277     list.append(block->getExternalResources());
278   }
279   return list;
280 }
281
282 void GroupBlock::generateVHDL(const QString& path) throw(Exception) {
283
284   QString coreFile = "";
285
286   coreFile = path;  
287   coreFile.append(Parameters::normalizeName(name));
288   coreFile.append(".vhd");
289
290   QFile vhdlCore(coreFile);
291
292   if (!vhdlCore.open(QIODevice::WriteOnly)) {
293     throw(Exception(VHDLFILE_NOACCESS));
294   }
295
296   cout << "generate VHDL of block " << qPrintable(name) << " in " << qPrintable(coreFile) << endl;
297   QTextStream outCore(&vhdlCore);
298
299   QDomElement dummyElt;
300   try {
301     generateComments(outCore,dummyElt,"");
302     generateLibraries(outCore,dummyElt);
303     generateEntity(outCore);
304     generateArchitecture(outCore,dummyElt);
305
306     foreach(AbstractBlock* block, blocks) {
307       block->generateVHDL(path);
308     }
309   }
310   catch(Exception err) {
311     throw(err);
312   }
313
314   vhdlCore.close();
315 }
316
317
318 void GroupBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) {
319   out << " -- VHDL generated automatically for " << name << " --" << endl << endl;
320 }
321
322 void GroupBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) {
323
324   out << "library IEEE;" << endl;
325   out << "use IEEE.STD_LOGIC_1164.all;" << endl;
326   out << "use IEEE.numeric_std.all;" << endl;
327
328 }
329
330 void GroupBlock::generateEntityOrComponentBody(QTextStream& out, int indentLevel, bool hasController) throw(Exception) {
331
332   int i;
333   QString indent = "";
334   for(i=0;i<indentLevel;i++) {
335     indent += " ";
336   }
337
338   QList<BlockParameter*> listGenerics = getGenericParameters();
339   QList<AbstractInterface*> listInputs = getInputs();
340   QList<AbstractInterface*> listOutputs = getOutputs();
341   QList<AbstractInterface*> listBidirs = getBidirs();
342
343   if (!listGenerics.isEmpty()) {
344     out << indent << "  generic (" << endl;
345     for(i=0;i<listGenerics.size()-1;i++) {
346       out << indent << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl;
347     }
348     out << indent << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl;
349     out << indent << "    );" << endl;
350   }
351
352   out << indent << "  port (" << endl;
353
354   // Generation of the clk & rst signals
355   out << indent << "    -- clk/rst" << endl;
356   foreach(AbstractInterface* iface, listInputs) {
357     if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) {
358       out << indent << "    " << iface->getName() << " : in std_logic;" << endl;
359     }
360   }
361
362   int count = 0;
363   foreach(AbstractInterface* iface, getInterfaces()) {
364     if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++;
365   }
366   // Generation of the data/control signals
367
368   int flag = 0;
369   bool first = true;
370
371   foreach(AbstractInterface* iface, listInputs) {
372     if(iface->getPurpose() == AbstractInterface::Data) {
373       if (first) {
374         out << indent << "    -- input data ports" << endl;
375         first = false;
376       }
377       count--;
378       if (count == 0) flag = AbstractInterface::NoComma;
379       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
380     }
381   }
382   first = true;
383   foreach(AbstractInterface* iface, listInputs) {
384     if(iface->getPurpose() == AbstractInterface::Control) {
385       if (first) {
386         out << indent << "    -- input control ports" << endl;
387         first = false;
388       }
389       count--;
390       if (count == 0) flag = AbstractInterface::NoComma;
391       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
392     }
393   }
394   first = true;
395   foreach(AbstractInterface* iface, listOutputs) {
396     if(iface->getPurpose() == AbstractInterface::Data) {
397       if (first) {
398         out << indent << "    -- output data ports" << endl;
399         first = false;
400       }
401       count--;
402       if (count == 0) flag = AbstractInterface::NoComma;
403       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
404     }
405   }
406   first = true;
407   foreach(AbstractInterface* iface, listOutputs) {
408     if(iface->getPurpose() == AbstractInterface::Control) {
409       if (first) {
410         out << indent << "    -- output control ports" << endl;
411         first = false;
412       }
413       count--;
414       if (count == 0) flag = AbstractInterface::NoComma;
415       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
416     }
417   }
418   first = true;
419   foreach(AbstractInterface* iface, listBidirs) {
420     if(iface->getPurpose() == AbstractInterface::Data) {
421       if (first) {
422         out << indent << "    -- bidirs data ports" << endl;
423         first = false;
424       }
425       count--;
426       if (count == 0) flag = AbstractInterface::NoComma;
427       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
428     }
429   }
430   out << indent << "    );" << endl << endl;
431 }
432
433 void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(Exception) {
434
435   int i;
436
437   out << "architecture rtl of " << name << " is " << endl << endl;
438
439   // generate type for delays, if needed.
440   QList<int> modWidth;
441   foreach(AbstractBlock* block, blocks) {
442     QList<AbstractInterface*> listCtlInputs = block->getControlInputs();
443     foreach(AbstractInterface* iface, listCtlInputs) {
444       ConnectedInterface* connCtlIface = AI_TO_CON(iface);
445       AbstractInputModifier* modifier = connCtlIface->getInputModifier();
446       if (modifier != NULL) {
447         ConnectedInterface* connIface = AI_TO_CON(connCtlIface->getAssociatedIface());
448         int w = connIface->getWidth();
449         if (w == -1) throw(Exception(INVALID_VALUE));
450         if (!modWidth.contains(w)) {
451           modWidth.append(w);
452         }
453       }
454     }
455   }
456   if (modWidth.size() > 0) {
457
458     out << "  -- types for modified inputs" << endl;
459     out << "  type vector_of_std_logic is array (natural range <>) of std_logic;" << endl;
460     foreach(int w, modWidth) {
461       QString mw = "";
462       mw.setNum(w);
463       QString mwm1 = "";
464       mwm1.setNum(w-1);
465       out << "  type vector_of_std_logic_vector"<< mw << " is array (natural range <>) of std_logic_vector(" << mwm1 << " downto 0);" << endl;
466     }
467     out << endl;
468   }
469
470
471   // generate the components
472   foreach(AbstractBlock* block, blocks) {
473     try {
474       block->generateComponent(out,false);
475     }
476     catch(Exception e) {
477       throw(e);
478     }
479   }
480
481   out << endl;
482   // generate signals
483   out << "  ----------------------------" << endl;
484   out << "  --  SIGNALS" << endl;
485   out << "  ----------------------------" << endl << endl;
486
487   // signals to synchronize inputs
488   out << "  -- signals to synchronize inputs" << endl;
489   foreach(AbstractInterface* iface, getInputs()) {
490     if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
491       QString name = iface->toVHDL(AbstractInterface::Signal,0);
492       name.replace(" : ","_sync : ");
493       out << "  signal " << name<< endl;
494     }
495   }
496   out << endl;
497
498   // "normal" signals
499   foreach(AbstractBlock* block, blocks) {
500     try {
501       out << "  -- signals from output ports of " << block->getName() << endl;
502       QList<AbstractInterface*> listOutputs = block->getOutputs();
503       foreach(AbstractInterface* iface, listOutputs) {
504         if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
505           out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
506         }
507         else if (block->getName() == "clkrstgen") {
508           if ((iface->getPurpose() == AbstractInterface::Clock)||(iface->getPurpose() == AbstractInterface::Reset)) {
509             out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
510           }
511         }
512       }
513     }
514     catch(Exception e) {
515       throw(e);
516     }
517     out << endl;
518   }
519
520   // signal for modifiers
521   foreach(AbstractBlock* block, blocks) {
522     bool hasModif = false;
523     QList<AbstractInterface*> listCtlInputs = block->getControlInputs();
524
525     foreach(AbstractInterface* iface, listCtlInputs) {
526       ConnectedInterface* connCtlIface = AI_TO_CON(iface);
527       AbstractInputModifier* modifier = connCtlIface->getInputModifier();
528       if (modifier != NULL) {
529         hasModif = true;
530         break;
531       }
532     }
533     if (hasModif) {
534       try {
535         out << "  -- signals for modified input ports of " << block->getName() << endl;
536         foreach(AbstractInterface* iface, listCtlInputs) {
537           ConnectedInterface* connCtlIface = AI_TO_CON(iface);
538           AbstractInputModifier* modifier = connCtlIface->getInputModifier();
539           if (modifier != NULL) {
540             out << modifier->toVHDL(AbstractInputModifier::Signal,0) << endl;
541           }
542         }
543       }
544       catch(Exception e) {
545         throw(e);
546       }
547       out << endl;
548     }
549   }
550
551   out << "begin" << endl;
552
553   // generate signals that goes to the output ports
554
555   out << "  -- connections to output ports of " << name << endl;
556   QList<AbstractInterface*> listOutputs = getOutputs();
557   foreach(AbstractInterface* iface, listOutputs) {
558     if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
559       ConnectedInterface* connIface = AI_TO_CON(iface);
560       ConnectedInterface* fromIface = connIface->getConnectedFrom();
561       out << "  " << connIface->getName() << " <= " << fromIface->toVHDL(AbstractInterface::Instance,0) << ";" << endl;
562     }
563   }
564
565   out << endl;
566
567
568
569   // generate instances
570   foreach(AbstractBlock* block, blocks) {
571     try {
572       out << "  " << block->getName() << "_1 : " << block->getName() << endl;
573
574       QList<BlockParameter*> listGenerics = block->getGenericParameters();
575       QList<AbstractInterface*> listInputs = block->getInputs();
576       QList<AbstractInterface*> listOutputs = block->getOutputs();
577       QList<AbstractInterface*> listBidirs = block->getBidirs();
578
579       if (!listGenerics.isEmpty()) {
580         out << "    generic map (" << endl;
581         for(i=0;i<listGenerics.size()-1;i++) {
582           out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl;
583         }
584         out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl;
585         out << "    )" << endl;
586       }
587
588       out << "    port map (" << endl;
589       QString portMap = "";
590
591       for(i=0;i<listInputs.size();i++) {
592         ConnectedInterface* connIface = AI_TO_CON(listInputs.at(i));
593         ConnectedInterface* fromIface = connIface->getConnectedFrom();
594
595         if (fromIface->isFunctionalInterface()) {
596           portMap += "      " + connIface->getName() + " => ";
597           bool hasMod = false;
598           if (connIface->getPurpose() == AbstractInterface::Data) {
599             ConnectedInterface* connCtlIface = AI_TO_CON(connIface->getAssociatedIface());
600             if ((connCtlIface != NULL) && (connCtlIface->getInputModifier() != NULL)) {
601               hasMod = true;
602             }
603           }
604           else if (connIface->getPurpose() == AbstractInterface::Control) {
605             if (connIface->getInputModifier() != NULL) {
606               hasMod = true;
607             }
608           }
609           if (hasMod) {
610             portMap += connIface->getOwner()->getName()+"_"+connIface->getName()+"_mod,\n";
611           }
612           else {
613             portMap += fromIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
614           }
615         }
616         else if (fromIface->isGroupInterface()) {
617           if ((fromIface->getOwner()->isTopGroupBlock()) && ((fromIface->getPurpose() == AbstractInterface::Data)||(fromIface->getPurpose() == AbstractInterface::Control))) {
618             portMap += "      " + connIface->getName() + " => " + fromIface->getOwner()->getName()+ "_"+ fromIface->getName() + "_sync,\n";
619           }
620           else {
621             portMap += "      " + connIface->getName() + " => " + fromIface->getName() + ",\n";
622           }
623         }
624       }
625       if (listOutputs.size()>0) {
626         for(i=0;i<listOutputs.size();i++) {
627           ConnectedInterface* connIface = AI_TO_CON(listOutputs.at(i));
628           portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
629         }
630       }
631       if (listBidirs.size()>0) {
632         for(i=0;i<listBidirs.size();i++) {
633           ConnectedInterface* connIface = AI_TO_CON(listBidirs.at(i));
634           portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
635         }
636       }
637       portMap.chop(2);
638       out << portMap << endl;
639
640
641       out << "    );" << endl;
642     }
643     catch(Exception e) {
644       throw(e);
645     }
646     out << endl;
647   }
648
649   // generate input modifiers
650   foreach(AbstractBlock* block, blocks) {
651
652     foreach(AbstractInterface* iface, block->getControlInputs()) {
653       ConnectedInterface* connIface = AI_TO_CON(iface);
654       // check if it is connected
655       if (connIface->getConnectedFrom() == NULL) {
656         throw(Exception(IFACE_NOT_CONNECTED,this));
657       }
658       AbstractInputModifier* modifier = connIface->getInputModifier();
659       if (modifier != NULL) {
660         try {
661           out << modifier->toVHDL(AbstractInputModifier::Architecture,0) << endl;
662         }
663         catch(Exception e) {
664           throw(e);
665         }
666       }
667     }
668   }
669
670   if (topGroup) {
671     // generate input sync process
672     out << "  -- process to synchronize inputs of top group" << endl;
673     out << "sync_inputs : process(from_clkrstgen_clk,from_clkrstgen_reset)" << endl;
674     out << "  begin" << endl;
675     out << "    if from_clkrstgen_reset = '1' then" << endl;
676     foreach(AbstractInterface* iface, getInputs()) {
677       if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
678         if (iface->getWidth() == 0) {
679           out << "      " << name << "_" << iface->getName() << "_sync <= '0';" << endl;
680         }
681         else {
682           out << "      " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl;
683         }
684       }
685     }
686     out << "    elsif rising_edge(from_clkrstgen_clk) then" << endl;
687     foreach(AbstractInterface* iface, getInputs()) {
688       if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
689         if (iface->getWidth() == 0) {
690           out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
691         }
692         else {
693           out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
694         }
695       }
696     }
697     out << "    end if;" << endl;
698     out << "  end process sync_inputs;" << endl;
699
700     out << endl;
701   }
702
703   out << "end architecture rtl;" << endl;
704 }
705
706 void GroupBlock::generateController(QTextStream &out) throw(Exception) {
707   
708 }
709