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

Private GIT Repository
moved clocks list to graph
[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(GroupBlock *_parent, bool createIfaces) throw(Exception) :  AbstractBlock() {
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     cout << "computing compat and output for " << qPrintable(block->getName()) << endl;
206     
207
208     try {
209       block->checkInputPatternCompatibility();
210     }
211     catch(Exception e) {      
212       cout << qPrintable(block->getName()) << " is not compatible with its input pattern" << endl;
213       throw(e);
214     }   
215     
216     try {
217       block->computeOutputPattern();
218     }
219     catch(Exception e) {
220       cout << "cannot finalize output pattern computation of " << qPrintable(block->getName()) << endl;
221       throw(e);
222     }
223     canCompute = true;
224
225     /* add other blocks connected from block to the fifo but only if
226        all their connected inputs are connected to blocks that have
227        a traversalLevel >=0
228      */
229     foreach(AbstractInterface* iface, block->getControlOutputs()) {
230       ConnectedInterface* conn = (ConnectedInterface*)iface;
231       foreach(ConnectedInterface* connTo, conn->getConnectedTo()) {
232
233         AbstractBlock* block1 = connTo->getOwner();
234         cout << "testing if " << qPrintable(block1->getName()) << " has all connected inputs connected to already processed blocks" << endl;
235         bool addIt = true;
236         int maxLevel = 0;
237
238         foreach(AbstractInterface* iface, block1->getControlInputs()) {
239           //cout << qPrintable(iface->getName()) << " of " << qPrintable(iface->getOwner()->getName()) << " connected to " << endl;
240           ConnectedInterface* connFrom = ((ConnectedInterface*)iface)->getConnectedFrom();
241           //cout << qPrintable(connFrom->getName()) << " of " << qPrintable(connFrom->getOwner()->getName()) << endl;
242
243           if ((connFrom != NULL) && (connFrom->getOwner()->getOutputPatternComputed() == false)) {
244             addIt = false;
245             break;
246           }
247           else {
248             if (connFrom->getOwner()->getTraversalLevel() > maxLevel) maxLevel = connFrom->getOwner()->getTraversalLevel();
249           }
250         }
251
252         if (addIt) {
253           cout << "adding " << qPrintable(block1->getName()) << " to the FIFO" << endl;
254           block1->setTraversalLevel(maxLevel+1); // level 0 = first blocks to be evaluated
255           fifo.append(block1);
256         }
257       }
258     }
259   }
260
261   if (canCompute) {
262     foreach(AbstractInterface* iface, getControlOutputs()) {
263       ConnectedInterface* connIface = AI_TO_CON(iface);
264       QList<char>* pattern = new QList<char>(*(connIface->getConnectedFrom()->getOutputPattern()));
265       connIface->setOutputPattern(pattern);
266     }
267     setOutputPatternComputed(true);
268   }
269 }
270
271 QList<QString> GroupBlock::getExternalResources() {
272
273   QList<QString> list;
274   foreach(AbstractBlock* block, blocks) {
275     list.append(block->getExternalResources());
276   }
277   return list;
278 }
279
280 void GroupBlock::generateVHDL(const QString& path) throw(Exception) {
281
282   QString coreFile = "";
283
284   coreFile = path;  
285   coreFile.append(Parameters::normalizeName(name));
286   coreFile.append(".vhd");
287
288   QFile vhdlCore(coreFile);
289
290   if (!vhdlCore.open(QIODevice::WriteOnly)) {
291     throw(Exception(VHDLFILE_NOACCESS));
292   }
293
294   cout << "generate VHDL of block " << qPrintable(name) << " in " << qPrintable(coreFile) << endl;
295   QTextStream outCore(&vhdlCore);
296
297   QDomElement dummyElt;
298   try {
299     generateComments(outCore,dummyElt,"");
300     generateLibraries(outCore,dummyElt);
301     generateEntity(outCore);
302     generateArchitecture(outCore,dummyElt);
303
304     foreach(AbstractBlock* block, blocks) {
305       block->generateVHDL(path);
306     }
307   }
308   catch(Exception err) {
309     throw(err);
310   }
311
312   vhdlCore.close();
313 }
314
315
316 void GroupBlock::generateComments(QTextStream& out, QDomElement &elt, QString coreFile) throw(Exception) {
317   out << " -- VHDL generated automatically for " << name << " --" << endl << endl;
318 }
319
320 void GroupBlock::generateLibraries(QTextStream& out, QDomElement &elt) throw(Exception) {
321
322   out << "library IEEE;" << endl;
323   out << "use IEEE.STD_LOGIC_1164.all;" << endl;
324   out << "use IEEE.numeric_std.all;" << endl;
325
326 }
327
328 void GroupBlock::generateEntityOrComponentBody(QTextStream& out, int indentLevel, bool hasController) throw(Exception) {
329
330   int i;
331   QString indent = "";
332   for(i=0;i<indentLevel;i++) {
333     indent += " ";
334   }
335
336   QList<BlockParameter*> listGenerics = getGenericParameters();
337   QList<AbstractInterface*> listInputs = getInputs();
338   QList<AbstractInterface*> listOutputs = getOutputs();
339   QList<AbstractInterface*> listBidirs = getBidirs();
340
341   if (!listGenerics.isEmpty()) {
342     out << indent << "  generic (" << endl;
343     for(i=0;i<listGenerics.size()-1;i++) {
344       out << indent << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity, 0) << endl;
345     }
346     out << indent << "    " << listGenerics.at(i)->toVHDL(BlockParameter::Entity,BlockParameter::NoComma) << endl;
347     out << indent << "    );" << endl;
348   }
349
350   out << indent << "  port (" << endl;
351
352   // Generation of the clk & rst signals
353   out << indent << "    -- clk/rst" << endl;
354   foreach(AbstractInterface* iface, listInputs) {
355     if(iface->getPurpose() == AbstractInterface::Clock || iface->getPurpose() == AbstractInterface::Reset) {
356       out << indent << "    " << iface->getName() << " : in std_logic;" << endl;
357     }
358   }
359
360   int count = 0;
361   foreach(AbstractInterface* iface, getInterfaces()) {
362     if((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) count++;
363   }
364   // Generation of the data/control signals
365
366   int flag = 0;
367   bool first = true;
368
369   foreach(AbstractInterface* iface, listInputs) {
370     if(iface->getPurpose() == AbstractInterface::Data) {
371       if (first) {
372         out << indent << "    -- input data ports" << endl;
373         first = false;
374       }
375       count--;
376       if (count == 0) flag = AbstractInterface::NoComma;
377       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
378     }
379   }
380   first = true;
381   foreach(AbstractInterface* iface, listInputs) {
382     if(iface->getPurpose() == AbstractInterface::Control) {
383       if (first) {
384         out << indent << "    -- input control ports" << endl;
385         first = false;
386       }
387       count--;
388       if (count == 0) flag = AbstractInterface::NoComma;
389       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
390     }
391   }
392   first = true;
393   foreach(AbstractInterface* iface, listOutputs) {
394     if(iface->getPurpose() == AbstractInterface::Data) {
395       if (first) {
396         out << indent << "    -- output data ports" << endl;
397         first = false;
398       }
399       count--;
400       if (count == 0) flag = AbstractInterface::NoComma;
401       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
402     }
403   }
404   first = true;
405   foreach(AbstractInterface* iface, listOutputs) {
406     if(iface->getPurpose() == AbstractInterface::Control) {
407       if (first) {
408         out << indent << "    -- output control ports" << endl;
409         first = false;
410       }
411       count--;
412       if (count == 0) flag = AbstractInterface::NoComma;
413       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
414     }
415   }
416   first = true;
417   foreach(AbstractInterface* iface, listBidirs) {
418     if(iface->getPurpose() == AbstractInterface::Data) {
419       if (first) {
420         out << indent << "    -- bidirs data ports" << endl;
421         first = false;
422       }
423       count--;
424       if (count == 0) flag = AbstractInterface::NoComma;
425       out << indent << "    " << iface->toVHDL(AbstractInterface::Entity, flag) << endl;
426     }
427   }
428   out << indent << "    );" << endl << endl;
429 }
430
431 void GroupBlock::generateArchitecture(QTextStream& out, QDomElement &elt) throw(Exception) {
432
433   int i;
434
435   out << "architecture rtl of " << name << " is " << endl << endl;
436
437   // generate type for delays, if needed.
438   QList<int> modWidth;
439   foreach(AbstractBlock* block, blocks) {
440     QList<AbstractInterface*> listCtlInputs = block->getControlInputs();
441     foreach(AbstractInterface* iface, listCtlInputs) {
442       ConnectedInterface* connCtlIface = AI_TO_CON(iface);
443       AbstractInputModifier* modifier = connCtlIface->getInputModifier();
444       if (modifier != NULL) {
445         ConnectedInterface* connIface = AI_TO_CON(connCtlIface->getAssociatedIface());
446         int w = connIface->getWidth();
447         if (w == -1) throw(Exception(INVALID_VALUE));
448         if (!modWidth.contains(w)) {
449           modWidth.append(w);
450         }
451       }
452     }
453   }
454   if (modWidth.size() > 0) {
455
456     out << "  -- types for modified inputs" << endl;
457     out << "  type vector_of_std_logic is array (natural range <>) of std_logic;" << endl;
458     foreach(int w, modWidth) {
459       QString mw = "";
460       mw.setNum(w);
461       QString mwm1 = "";
462       mwm1.setNum(w-1);
463       out << "  type vector_of_std_logic_vector"<< mw << " is array (natural range <>) of std_logic_vector(" << mwm1 << " downto 0);" << endl;
464     }
465     out << endl;
466   }
467
468
469   // generate the components
470   foreach(AbstractBlock* block, blocks) {
471     try {
472       block->generateComponent(out,false);
473     }
474     catch(Exception e) {
475       throw(e);
476     }
477   }
478
479   out << endl;
480   // generate signals
481   out << "  ----------------------------" << endl;
482   out << "  --  SIGNALS" << endl;
483   out << "  ----------------------------" << endl << endl;
484
485   // signals to synchronize inputs
486   out << "  -- signals to synchronize inputs" << endl;
487   foreach(AbstractInterface* iface, getInputs()) {
488     if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
489       QString name = iface->toVHDL(AbstractInterface::Signal,0);
490       name.replace(" : ","_sync : ");
491       out << "  signal " << name<< endl;
492     }
493   }
494   out << endl;
495
496   // "normal" signals
497   foreach(AbstractBlock* block, blocks) {
498     try {
499       out << "  -- signals from output ports of " << block->getName() << endl;
500       QList<AbstractInterface*> listOutputs = block->getOutputs();
501       foreach(AbstractInterface* iface, listOutputs) {
502         if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
503           out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
504         }
505         else if (block->getName() == "clkrstgen") {
506           if ((iface->getPurpose() == AbstractInterface::Clock)||(iface->getPurpose() == AbstractInterface::Reset)) {
507             out << "  signal " << iface->toVHDL(AbstractInterface::Signal,0) << endl;
508           }
509         }
510       }
511     }
512     catch(Exception e) {
513       throw(e);
514     }
515     out << endl;
516   }
517
518   // signal for modifiers
519   foreach(AbstractBlock* block, blocks) {
520     bool hasModif = false;
521     QList<AbstractInterface*> listCtlInputs = block->getControlInputs();
522
523     foreach(AbstractInterface* iface, listCtlInputs) {
524       ConnectedInterface* connCtlIface = AI_TO_CON(iface);
525       AbstractInputModifier* modifier = connCtlIface->getInputModifier();
526       if (modifier != NULL) {
527         hasModif = true;
528         break;
529       }
530     }
531     if (hasModif) {
532       try {
533         out << "  -- signals for modified input ports of " << block->getName() << endl;
534         foreach(AbstractInterface* iface, listCtlInputs) {
535           ConnectedInterface* connCtlIface = AI_TO_CON(iface);
536           AbstractInputModifier* modifier = connCtlIface->getInputModifier();
537           if (modifier != NULL) {
538             out << modifier->toVHDL(AbstractInputModifier::Signal,0) << endl;
539           }
540         }
541       }
542       catch(Exception e) {
543         throw(e);
544       }
545       out << endl;
546     }
547   }
548
549   out << "begin" << endl;
550
551   // generate signals that goes to the output ports
552
553   out << "  -- connections to output ports of " << name << endl;
554   QList<AbstractInterface*> listOutputs = getOutputs();
555   foreach(AbstractInterface* iface, listOutputs) {
556     if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
557       ConnectedInterface* connIface = AI_TO_CON(iface);
558       ConnectedInterface* fromIface = connIface->getConnectedFrom();
559       out << "  " << connIface->getName() << " <= " << fromIface->toVHDL(AbstractInterface::Instance,0) << ";" << endl;
560     }
561   }
562
563   out << endl;
564
565
566
567   // generate instances
568   foreach(AbstractBlock* block, blocks) {
569     try {
570       out << "  " << block->getName() << "_1 : " << block->getName() << endl;
571
572       QList<BlockParameter*> listGenerics = block->getGenericParameters();
573       QList<AbstractInterface*> listInputs = block->getInputs();
574       QList<AbstractInterface*> listOutputs = block->getOutputs();
575       QList<AbstractInterface*> listBidirs = block->getBidirs();
576
577       if (!listGenerics.isEmpty()) {
578         out << "    generic map (" << endl;
579         for(i=0;i<listGenerics.size()-1;i++) {
580           out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance, BlockParameter::NoComma) << "," << endl;
581         }
582         out << "      " << listGenerics.at(i)->toVHDL(BlockParameter::Instance,BlockParameter::NoComma) << endl;
583         out << "    )" << endl;
584       }
585
586       out << "    port map (" << endl;
587       QString portMap = "";
588
589       for(i=0;i<listInputs.size();i++) {
590         ConnectedInterface* connIface = AI_TO_CON(listInputs.at(i));
591         ConnectedInterface* fromIface = connIface->getConnectedFrom();
592
593         if (fromIface->isFunctionalInterface()) {
594           portMap += "      " + connIface->getName() + " => ";
595           bool hasMod = false;
596           if (connIface->getPurpose() == AbstractInterface::Data) {
597             ConnectedInterface* connCtlIface = AI_TO_CON(connIface->getAssociatedIface());
598             if ((connCtlIface != NULL) && (connCtlIface->getInputModifier() != NULL)) {
599               hasMod = true;
600             }
601           }
602           else if (connIface->getPurpose() == AbstractInterface::Control) {
603             if (connIface->getInputModifier() != NULL) {
604               hasMod = true;
605             }
606           }
607           if (hasMod) {
608             portMap += connIface->getOwner()->getName()+"_"+connIface->getName()+"_mod,\n";
609           }
610           else {
611             portMap += fromIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
612           }
613         }
614         else if (fromIface->isGroupInterface()) {
615           if ((fromIface->getOwner()->isTopGroupBlock()) && ((fromIface->getPurpose() == AbstractInterface::Data)||(fromIface->getPurpose() == AbstractInterface::Control))) {
616             portMap += "      " + connIface->getName() + " => " + fromIface->getOwner()->getName()+ "_"+ fromIface->getName() + "_sync,\n";
617           }
618           else {
619             portMap += "      " + connIface->getName() + " => " + fromIface->getName() + ",\n";
620           }
621         }
622       }
623       if (listOutputs.size()>0) {
624         for(i=0;i<listOutputs.size();i++) {
625           ConnectedInterface* connIface = AI_TO_CON(listOutputs.at(i));
626           portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
627         }
628       }
629       if (listBidirs.size()>0) {
630         for(i=0;i<listBidirs.size();i++) {
631           ConnectedInterface* connIface = AI_TO_CON(listBidirs.at(i));
632           portMap += "      " + connIface->getName() + " => " + connIface->toVHDL(AbstractInterface::Instance, AbstractInterface::NoComma) + ",\n";
633         }
634       }
635       portMap.chop(2);
636       out << portMap << endl;
637
638
639       out << "    );" << endl;
640     }
641     catch(Exception e) {
642       throw(e);
643     }
644     out << endl;
645   }
646
647   // generate input modifiers
648   foreach(AbstractBlock* block, blocks) {
649
650     foreach(AbstractInterface* iface, block->getControlInputs()) {
651       ConnectedInterface* connIface = AI_TO_CON(iface);
652       // check if it is connected
653       if (connIface->getConnectedFrom() == NULL) {
654         throw(Exception(IFACE_NOT_CONNECTED,this));
655       }
656       AbstractInputModifier* modifier = connIface->getInputModifier();
657       if (modifier != NULL) {
658         try {
659           out << modifier->toVHDL(AbstractInputModifier::Architecture,0) << endl;
660         }
661         catch(Exception e) {
662           throw(e);
663         }
664       }
665     }
666   }
667
668   if (topGroup) {
669     // generate input sync process
670     out << "  -- process to synchronize inputs of top group" << endl;
671     out << "sync_inputs : process(from_clkrstgen_clk,from_clkrstgen_reset)" << endl;
672     out << "  begin" << endl;
673     out << "    if from_clkrstgen_reset = '1' then" << endl;
674     foreach(AbstractInterface* iface, getInputs()) {
675       if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
676         if (iface->getWidth() == 0) {
677           out << "      " << name << "_" << iface->getName() << "_sync <= '0';" << endl;
678         }
679         else {
680           out << "      " << name << "_" << iface->getName() << "_sync <= (others => '0');" << endl;
681         }
682       }
683     }
684     out << "    elsif rising_edge(from_clkrstgen_clk) then" << endl;
685     foreach(AbstractInterface* iface, getInputs()) {
686       if ((iface->getPurpose() == AbstractInterface::Data)||(iface->getPurpose() == AbstractInterface::Control)) {
687         if (iface->getWidth() == 0) {
688           out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
689         }
690         else {
691           out << "      " << name << "_" << iface->getName() << "_sync <= " << iface->getName() << ";" << endl;
692         }
693       }
694     }
695     out << "    end if;" << endl;
696     out << "  end process sync_inputs;" << endl;
697
698     out << endl;
699   }
700
701   out << "end architecture rtl;" << endl;
702 }
703
704 void GroupBlock::generateController(QTextStream &out) throw(Exception) {
705   
706 }
707