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

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