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

Private GIT Repository
finished testbench generation
[blast.git] / Dispatcher.cpp
1 #include "Dispatcher.h"
2 #include "Parameters.h"
3 #include "MainWindow.h"
4
5 #include "ExternalResource.h"
6
7 #include "Graph.h"
8 #include "ReferenceBlock.h"
9 #include "GroupBlock.h"
10 #include "FunctionalBlock.h"
11
12 #include "ConnectedInterface.h"
13 #include "ReferenceInterface.h"
14 #include "GroupInterface.h"
15 #include "FunctionalInterface.h"
16
17 #include "GroupWidget.h"
18 #include "GroupScene.h"
19 #include "GroupItem.h"
20 #include "BoxItem.h"
21 #include "StimuliItem.h"
22 #include "InterfaceItem.h"
23 #include "ConnectionItem.h"
24
25 #include "BlockLibraryWidget.h"
26 #include "BlockLibraryTree.h"
27
28 #include "AbstractInputModifier.h"
29 #include "DelayInputModifier.h"
30
31
32 #include "InterfacePropertiesDialog.h"
33
34 #include <QHashIterator>
35
36 int Dispatcher::sceneCounter = 0;
37
38 Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
39   params = _params;
40   mainWindow =_window;
41   params->setDispatcher(this);
42   currentGroupWidget = NULL;
43   topGroupWidget = NULL;
44 }
45
46 GroupWidget *Dispatcher::loadProject(const QString& filename) {
47
48   QDomElement root;
49   try {
50     root = params->openProjectFile(filename);
51   }
52   catch(Exception err) {
53     return NULL;
54   }
55
56   /*
57   // creating the top widget/scene
58   topGroup = new GroupWidget(NULL,this,params);
59   currentGroup = topGroup;
60   // getting the newly created scene
61   GroupScene *scene = topGroup->getScene();
62
63   params->setTopScene(scene);
64   params->setCurrentScene(scene);
65 */
66   try {   
67     topGroupWidget = params->loadProject(root);
68   }
69   catch(Exception e){
70     cerr << qPrintable(e.getDefaultMessage()) << endl;
71     cerr << "Aborting ..." << endl;
72     // TO DO : deleteting topGroup and all
73     return NULL;
74   }
75
76   QFileInfo info(filename);
77   params->projectPath = info.absolutePath();
78   params->projectName = info.baseName();
79   cout << "project path = " << qPrintable(params->projectPath) << endl;
80   groupList.append(topGroupWidget);
81   return topGroupWidget;
82 }
83
84 void Dispatcher::closeCurrentProject() {
85
86   foreach(GroupWidget* win, groupList) {
87     win->deleteLater();
88   }
89   groupList.clear();
90   params->destroyGraph();
91   topGroupWidget = NULL;
92   currentGroupWidget = NULL;
93   sceneCounter = 0;
94 }
95
96 void Dispatcher::setSceneCounter(Context context, int value) {
97
98   if (context != Load) return;
99   sceneCounter = value;
100 }
101
102 bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
103   static QString fctName = "Dispatcher::createConnection()";
104 #ifdef DEBUG_FCTNAME
105   cout << "call to " << qPrintable(fctName) << endl;
106 #endif
107
108   bool testClock = false;
109   if (context == Design) {
110     testClock = true;
111   }
112
113   ConnectedInterface* ref1 = iface1->refInter;
114   ConnectedInterface* ref2 = iface2->refInter;  
115   // connect both interface
116
117   bool ok1 = false;
118   bool ok2 = false;
119
120   cout << "trying to create a connection between " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
121   cout << " and " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
122
123   // test the ref1->ref2 connection
124   if ((ref1->canConnectTo(ref2,testClock)) && (ref2->canConnectFrom(ref1,testClock))) {
125     ref1->connectTo(ref2);    
126     ok1 = true;
127   }
128   // if the first one did not work, test ref2->ref1
129   if ((ok1 == false) && (ref2->canConnectTo(ref1,testClock)) && (ref1->canConnectFrom(ref2,testClock))) {
130     ref2->connectTo(ref1);    
131     ok2 = true;
132   }
133   if ((ok1 == true) || (ok2 == true)) {    
134
135     if (ok1) {
136       cout << " ... done with " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
137       cout << " to " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
138       iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
139     }
140     else {
141       cout << "... done with " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName());
142       cout << " to " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName());
143       iface2->getOwner()->getScene()->createConnectionItem(iface2,iface1, visible);
144     }
145
146     cout << endl;
147
148     unselectAllItems(context);
149     params->unsaveModif = true;    
150     return true;
151   }
152   return false;
153 }
154
155
156 void Dispatcher::unselectAllItems(Context context, int direction){
157
158   GroupScene *scene = params->getCurrentScene();
159
160   foreach(BoxItem* block, scene->getBoxItems()) {
161     block->setSelected(false);
162     block->setCurrentInterface(NULL);
163   }
164   scene->unselecteInterfaces();
165   scene->update();
166 }
167
168 void Dispatcher::setCurrentGroupWidget(Context context, GroupWidget *win){
169   win->setFocus();
170   win->changeConnectionMode(-1);
171   currentGroupWidget = win;
172   params->setCurrentScene(win->getScene());
173 }
174
175 void Dispatcher::changeConnectionMode(Context context, int mode){
176
177   /*
178   foreach(GroupWidget* win, groupList){
179
180     QToolButton* buttonNewConnection = win->getButtonNewConnection();
181
182     QPalette pal = buttonNewConnection->palette();
183
184     if(mode == -1){
185       if(params->sceneMode != Parameters::EditOnConnection){
186         params->sceneMode = Parameters::EditOnConnection;
187         pal.setColor(QPalette::Button, QColor(Qt::lightGray));
188       } else {
189         params->sceneMode = Parameters::EditNoOperation;
190         pal.setColor(QPalette::Button, QColor("#edeceb"));
191       }
192     }
193     else if(mode == Parameters::EditOnConnection){
194       params->sceneMode = Parameters::EditOnConnection;
195       pal.setColor(QPalette::Button, QColor(Qt::lightGray));
196     }
197     else {
198       params->sceneMode = Parameters::EditNoOperation;
199       pal.setColor(QPalette::Button, QColor("#edeceb"));
200     }
201     unselectAllInterfaces();
202
203     buttonNewConnection->setAutoFillBackground(true);
204     buttonNewConnection->setPalette(pal);
205     buttonNewConnection->update();
206   }
207   */
208 }
209
210 void Dispatcher::generateVHDL(Context context) throw(Exception) {
211   static QString fctName = "Dispatcher::generateVHDL()";
212 #ifdef DEBUG_FCTNAME
213   cout << "call to " << qPrintable(fctName) << endl;
214 #endif
215   /* NB: only called in Design context */
216   if (context != Design) {
217     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
218     return;
219   }
220
221
222   QDir baseDir(params->projectPath);
223   QDir srcDir(params->projectPath+"/src");
224
225   if (!baseDir.exists()) {
226     cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl;
227     return;
228   }
229
230   if (srcDir.exists()) {
231     srcDir.removeRecursively();
232   }
233   baseDir.mkdir("src");
234
235   if (! baseDir.exists("testbench")) {
236     baseDir.mkdir("testbench");
237   }
238   if (! baseDir.exists("Makefile")) {
239     QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim");
240     QString dest = params->projectPath;
241     dest += "/Makefile";
242     make.copy(dest);
243   }
244
245   // generate VHDL + copying external resources
246   QString dest = params->projectPath;
247   dest += "/src/";  
248   try {    
249     params->getGraph()->generateVHDL(dest);
250
251     QList<QString> extResources = params->getGraph()->getExternalResources();
252     foreach(QString name, extResources) {
253       cout << qPrintable(name) << endl;
254       QList<ExternalResource*> lstRes = params->searchResourceByName(name);
255       foreach(ExternalResource* res, lstRes) {
256         QFile resFile(res->getFile());
257         QFileInfo info(res->getFile());
258         QString destFile = dest+info.fileName();
259         cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl;
260         resFile.copy(destFile);
261       }
262     }
263   }
264   catch(Exception e) {
265     throw(e);
266   }
267   // generate testbench
268   dest = params->projectPath;
269   dest += "/testbench/";
270   dest += params->projectName;
271   dest += "_tb.vhd";
272   try {
273     params->getGraph()->generateTestbench(params->projectName, dest);
274   }
275   catch(Exception e) {
276     throw(e);
277   }
278
279   // creating parameters file
280   QString paramName = params->projectPath+"/params-isim.txt";
281   QFile paramFile(paramName);
282   if (!paramFile.open(QIODevice::WriteOnly)) {
283     throw(Exception(PROJECTPATH_NOACCESS));
284   }
285   QTextStream out(&paramFile);
286   out << "PROJECT_NAME := " << params->projectName << endl << endl;
287   out << "SRC_DIR := src" << endl;
288   out << "TB_DIR := testbench" << endl << endl;
289   out << "VHDL_SRC := ";
290   QStringList filter;
291   filter << "*.vhd" ;
292   srcDir.setNameFilters(filter);
293   QStringList listVHDL = srcDir.entryList();
294   for(int j=0;j<listVHDL.size();j++) {
295     if (j > 0) {
296       out << "\t";
297     }
298     out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j));
299     if (j != listVHDL.size()-1) {
300       out << " \\";
301     }
302     out << endl;
303   }
304   out << endl;
305   out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl;
306   out << "TB_SRC := $(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl;
307   out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl;
308
309   paramFile.close();
310
311   QString msg = "VHDL generation completed successfully. Go to ";
312   msg += params->projectPath+" and type the following commands to launch a simulation:\n";
313   msg += "\tmake clean\n";
314   msg += "\tmake\n";
315   msg += "\tmake view\n";
316   QMessageBox::information(mainWindow,"VHDL generation", msg, QMessageBox::Ok);
317
318 }
319
320 void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){
321   static QString fctName = "Dispatcher::generateBlockVHDL()";
322 #ifdef DEBUG_FCTNAME
323   cout << "call to " << qPrintable(fctName) << endl;
324 #endif
325   /* NB: only called in Design context */
326   if (context != Design) {
327     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
328     return;
329   }
330
331
332   if (item->getRefBlock()->isFunctionalBlock()) {
333     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
334     try {
335       block->generateVHDL(params->projectPath);      
336     }
337     catch(Exception e) {
338       cout << qPrintable(e.getMessage()) << endl;
339     }
340   }
341 }
342
343 void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){
344   static QString fctName = "Dispatcher::renameFunctionalBlock()";
345 #ifdef DEBUG_FCTNAME
346   cout << "call to " << qPrintable(fctName) << endl;
347 #endif
348   /* NB: only called in Design context */
349   if (context != Design) {
350     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
351     return;
352   }
353
354     
355   GroupWidget* win = item->getScene()->getGroupWidget();
356   
357   bool ok = false;
358   QString text = "";  
359   while (!ok) {  
360     text = QInputDialog::getText(win, "Rename a functional block",
361                                        "New name:", QLineEdit::Normal,
362                                        item->getRefBlock()->getName(), &ok);
363     if (!ok) return;
364     
365     if (text == item->getRefBlock()->getName()) return;
366     
367     if( (text.isEmpty()) || (text.length() > 30)) {
368       QMessageBox::warning(win,"Error in given name",
369                            "the block name must be shorter than 30 characters, cannot be empty",
370                            QMessageBox::Ok);
371       ok = false;
372     }
373     else {
374       FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
375       if (block != NULL) {
376         QMessageBox::warning(win,"Error in given name",
377                              "the name provided is similar to that of another functional block within the group",
378                              QMessageBox::Ok);
379         ok = false;
380       }
381     }    
382   }  
383
384   item->getRefBlock()->setName(text);
385   item->nameChanged();
386 }
387
388 void Dispatcher::renameGroupBlock(Context context, GroupItem *item){
389   static QString fctName = "Dispatcher::renameGroupBlock()";
390 #ifdef DEBUG_FCTNAME
391   cout << "call to " << qPrintable(fctName) << endl;
392 #endif
393   /* NB: only called in Design context */
394   if (context != Design) {
395     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
396     return;
397   }
398
399   
400   GroupWidget* win = item->getScene()->getGroupWidget();
401   
402   bool ok = false;
403   QString text = "";
404   while (!ok) {  
405     text = QInputDialog::getText(win, "Rename a group",
406                                        "New name:", QLineEdit::Normal,
407                                        item->getRefBlock()->getName(), &ok);
408     if (!ok) return;
409     
410     if (text == item->getRefBlock()->getName()) return;
411     
412     if( (text.isEmpty()) || (text.length() > 30)) {
413       QMessageBox::warning(win,"Error in given name",
414                            "the block name must be shorter than 30 characters, cannot be empty",
415                            QMessageBox::Ok);
416       ok = false;
417     }
418     else {
419       GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
420       if (block != NULL) {
421         QMessageBox::warning(win,"Error in given name",
422                              "the name provided is similar to that of another group",
423                              QMessageBox::Ok);
424         ok = false;
425       }
426     }    
427   }
428   
429   item->getRefBlock()->setName(text);
430   if(item->getScene()->getGroupWidget()->isTopGroup()) {
431     mainWindow->setWindowTitle("blast - "+text);
432   }
433   else {
434     item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
435   }
436   item->nameChanged();
437   mainWindow->getLibrary()->updateComboScene();   
438 }
439
440 void Dispatcher::renameStimuliItem(Context context, StimuliItem *item){
441   static QString fctName = "Dispatcher::renameStimuliItem()";
442 #ifdef DEBUG_FCTNAME
443   cout << "call to " << qPrintable(fctName) << endl;
444 #endif
445   /* NB: only called in Design context */
446   if (context != Design) {
447     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
448     return;
449   }
450
451     
452   GroupWidget* win = item->getScene()->getGroupWidget();
453   
454   bool ok = false;
455   QString text = "";  
456   while (!ok) {  
457     text = QInputDialog::getText(win, "Rename a stimuli",
458                                        "New name:", QLineEdit::Normal,
459                                        item->getRefBlock()->getName(), &ok);
460     if (!ok) return;
461     
462     if (text == item->getRefBlock()->getName()) return;
463     
464     if( (text.isEmpty()) || (text.length() > 30)) {
465       QMessageBox::warning(win,"Error in given name",
466                            "the block name must be shorter than 30 characters, cannot be empty",
467                            QMessageBox::Ok);
468       ok = false;
469     }
470     else {
471       FunctionalBlock* block = params->getGraph()->getStimuliBlockByName(text);
472       if (block != NULL) {
473         QMessageBox::warning(win,"Error in given name",
474                              "the name provided is similar to that of another stimuli block within the top group",
475                              QMessageBox::Ok);
476         ok = false;
477       }
478     }    
479   }  
480
481   item->getRefBlock()->setName(text);
482   item->nameChanged();
483 }
484
485
486 void Dispatcher::renameInterface(Context context, InterfaceItem *item) {
487   static QString fctName = "Dispatcher::renameInterface()";
488 #ifdef DEBUG_FCTNAME
489   cout << "call to " << qPrintable(fctName) << endl;
490 #endif
491   /* NB: only called in Design context */
492   if (context != Design) {
493     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
494     return;
495   }
496
497   GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
498   
499   bool ok = false;
500   QString text = "";
501   while (!ok) {
502     text = QInputDialog::getText(win, "Rename an interface",
503                                        "New name:", QLineEdit::Normal,
504                                        item->refInter->getName(), &ok);
505    
506     if (!ok) return;
507     
508     if (text == item->refInter->getName()) return;
509     
510     if( (text.isEmpty()) || (text.length() > 30)) {
511       QMessageBox::warning(win,"Error in given name",
512                            "the interface name must be shorter than 30 characters, cannot be empty",
513                            QMessageBox::Ok);
514       ok = false;
515     }
516     else {
517       AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
518       if (iface != NULL) {
519         QMessageBox::warning(win,"Error in given name",
520                              "the name provided is similar to that of another interface",
521                              QMessageBox::Ok);
522         ok = false;
523       }
524     }
525   }
526   item->refInter->setName(text);
527   AbstractInterface* assoIface = item->refInter->getAssociatedIface();
528   if (assoIface != NULL) {
529     assoIface->setName(text+"_enb");
530   }
531   item->updateName(text);
532   item->getOwner()->nameChanged();  
533 }
534
535 void Dispatcher::showPatterns(Context context, InterfaceItem *item) {
536   static QString fctName = "Dispatcher::showPatterns()";
537 #ifdef DEBUG_FCTNAME
538   cout << "call to " << qPrintable(fctName) << endl;
539 #endif
540   /* NB: only called in Design context */
541   if (context != Design) {
542     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
543     return;
544   }
545
546   QString msg = "";
547   if (item->refInter->getDirection() == AbstractInterface::Input) {
548     msg = "Input pattern of iface ";
549     msg += item->refInter->getName();
550     msg += " owned by ";
551     msg += item->refInter->getOwner()->getName();
552     msg += " is:\n";
553     // get the precursor output pattern
554     ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
555     QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
556     // get the modifier
557     AbstractInputModifier* modifier = connIface->getInputModifier();
558     // check if the input is modified
559     if (modifier != NULL) {
560
561       out = modifier->getModifiedInput(out);
562     }
563
564     foreach(char c, *out) {
565       msg += QString::number((int)c);
566     }
567     msg += "\n";
568   }
569   else if (item->refInter->getDirection() == AbstractInterface::Output) {
570     msg = "Output pattern of iface ";
571     msg += item->refInter->getName();
572     msg += " owned by ";
573     msg += item->refInter->getOwner()->getName();
574     msg += " is:\n";
575     ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
576     if (iface->getOutputPattern() == NULL) return;
577     foreach(char c, *(iface->getOutputPattern())) {
578       msg += QString::number((int)c);
579     }
580     msg += "\n";
581   }
582   QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
583 }
584
585 void Dispatcher::showModifier(Context context, InterfaceItem *item) {
586   static QString fctName = "Dispatcher::showModifier()";
587 #ifdef DEBUG_FCTNAME
588   cout << "call to " << qPrintable(fctName) << endl;
589 #endif
590   /* NB: only called in Design context */
591   if (context != Design) {
592     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
593     return;
594   }
595
596   QString msg = "";
597   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
598   AbstractInputModifier* mod = assoIface->getInputModifier();
599   if (mod->isDelay()) {
600     DelayInputModifier* delay = (DelayInputModifier *)mod;
601     msg = "Pattern of iface ";
602     msg += item->refInter->getName();
603     msg += " owned by ";
604     msg += item->refInter->getOwner()->getName();
605     msg += " is modified by a simple delay of ";
606     msg += QString::number(delay->getDelayLength());
607
608   }
609   QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
610 }
611
612 void Dispatcher::removeModifier(Context context, InterfaceItem *item) {
613   static QString fctName = "Dispatcher::removeModifier()";
614 #ifdef DEBUG_FCTNAME
615   cout << "call to " << qPrintable(fctName) << endl;
616 #endif
617   /* NB: only called in Design context */
618   if (context != Design) {
619     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
620     return;
621   }
622
623
624   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
625   assoIface->clearInputModifier();
626 }
627
628
629 void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){
630   static QString fctName = "Dispatcher::duplicateBoxItem()";
631 #ifdef DEBUG_FCTNAME
632   cout << "call to " << qPrintable(fctName) << endl;
633 #endif
634   /* NB: only called in Design context */
635   if (context != Design) {
636     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
637     return;
638   }
639
640
641   GroupScene *scene = item->getScene();
642   AbstractBlock* block = item->getRefBlock();  
643   AbstractBlock *newBlock;
644
645   // only duplicate functional blocks
646   if(block->isFunctionalBlock()) {
647
648     // adding to the model
649     FunctionalBlock* funBlock = (FunctionalBlock*)block;
650     newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
651     // adding to the view
652     scene->createBoxItem(newBlock);
653
654     params->unsaveModif = true;
655   }
656 }
657
658 void Dispatcher::duplicateStimuliItem(Context context, StimuliItem *item) {
659   static QString fctName = "Dispatcher::duplicateStimuliItem()";
660 #ifdef DEBUG_FCTNAME
661   cout << "call to " << qPrintable(fctName) << endl;
662 #endif
663   /* NB: only called in Design context */
664   if (context != Design) {
665     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
666     return;
667   }
668
669
670   GroupScene *scene = item->getScene();
671   AbstractBlock* block = item->getRefBlock();  
672   AbstractBlock *newBlock;
673
674   // only duplicate functional blocks
675   if(block->isFunctionalBlock()) {
676
677     // adding to the model
678     FunctionalBlock* funBlock = (FunctionalBlock*)block;
679     newBlock = params->getGraph()->duplicateStimuliBlock(funBlock);
680     // adding to the view
681     scene->createStimuliItem(newBlock);
682
683     params->unsaveModif = true;
684   }
685 }
686
687 void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) {
688   static QString fctName = "Dispatcher::duplicateInterfaceItem()";
689 #ifdef DEBUG_FCTNAME
690   cout << "call to " << qPrintable(fctName) << endl;
691 #endif
692   /* NB: only called in Design context */
693   if (context != Design) {
694     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
695     return;
696   }
697
698
699   AbstractInterface *refI = item->refInter;
700   if (! refI->isFunctionalInterface()) return;
701
702   AbstractBlock *refB = refI->getOwner();
703   if(! refB->isFunctionalBlock()) return;
704
705   FunctionalInterface* iface = (FunctionalInterface*)refI;
706   AbstractInterface *cloneIface = iface->clone();
707   if (cloneIface == NULL) {
708     QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
709     return;
710   }
711
712   refB->addInterface(cloneIface);
713
714   InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
715   item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
716   
717   // creating control interface if needed
718   if (refI->getAssociatedIface() != NULL) {
719     QString ctlName = cloneIface->getName()+"_enb";
720     ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
721     refB->addInterface(ctlIface);
722     if (! ctlIface->setAssociatedIface(cloneIface)) {
723       cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
724     }
725   }
726 }
727
728
729 void Dispatcher::addBlock(Context context, int idCategory, int idBlock, int idScene, QHash<QString, int> clkRstToGen) {
730   static QString fctName = "Dispatcher::addBlock()";
731 #ifdef DEBUG_FCTNAME
732   cout << "call to " << qPrintable(fctName) << endl;
733 #endif
734   bool newStimuli = false;  
735
736   /* For now, this method is only used while designing and not loading */
737   if (context == Design) {
738     GroupScene *scene = getSceneById(idScene);
739     ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
740     // if block has no inputs, propose to add it as a source to top scene
741     if ((scene->isTopScene()) && (ref->isSourceBlock())) {
742       int ret = QMessageBox::question(NULL,"Adding a block to top scene","Selected block may be used as a stimuli for the top scene. Do you want to add it as a stimuli ?");
743       if (ret == QMessageBox::Yes) {
744         newStimuli = true;
745       }
746     }
747     if (newStimuli) {
748       FunctionalBlock* newOne = params->getGraph()->createStimuliBlock(ref, true);
749       StimuliItem* item = scene->createStimuliItem(newOne);
750       QHashIterator<QString,int> iter(clkRstToGen);
751       while (iter.hasNext()) {
752         iter.next();
753         AbstractInterface* iface = newOne->getIfaceFromName(iter.key());
754         if (iface->getPurpose() == AbstractInterface::Clock) {
755           connectStimuliItemClock(context,item,iface->getName(),iter.value());
756         }
757         else if (iface->getPurpose() == AbstractInterface::Reset) {
758           connectStimuliItemReset(context,item,iface->getName(),iter.value());
759         }
760       }
761     }
762     else {
763
764       GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
765       FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true);
766
767       // creating the box item
768       BoxItem* item = scene->createBoxItem(newOne);
769
770       QHashIterator<QString,int> iter(clkRstToGen);
771       while (iter.hasNext()) {
772         iter.next();
773         AbstractInterface* iface = newOne->getIfaceFromName(iter.key());
774         if (iface->getPurpose() == AbstractInterface::Clock) {
775           connectBoxItemClock(context,item,iface->getName(),iter.value());
776         }
777         else if (iface->getPurpose() == AbstractInterface::Reset) {
778           connectBoxItemReset(context,item,iface->getName(),iter.value());
779         }
780       }
781
782       params->blockToItem.insert(newOne,item);
783     }
784     params->unsaveModif = true;
785   }
786 }
787
788 void Dispatcher::addClkRstGenBlock(Context context, double frequency) {
789   static QString fctName = "Dispatcher::addClkRstGenBlock()";
790 #ifdef DEBUG_FCTNAME
791   cout << "call to " << qPrintable(fctName) << endl;
792 #endif
793
794
795   if (context == Design) {
796
797     params->getGraph()->addClock(frequency);
798
799     // get the top group
800     GroupBlock *group = params->getGraph()->getTopGroup();
801     GroupScene *scene = topGroupWidget->getScene();
802
803     // creating the clkrstgen block
804     ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
805     FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true);
806
807     QString name = "clkrstgen_";
808     name += QString::number(params->getGraph()->getClocks().size()-1);
809     newOne->setName(name);
810
811     // creating the box item
812     BoxItem* item = scene->createBoxItem(newOne, BoxItem::Left, AbstractBoxItem::Dimension);
813     item->setVisible(false);
814
815     ConnectedInterface* fromIfaceClk = NULL;
816     ConnectedInterface* fromIfaceReset = NULL;
817     QString clkName = "ext_clk_"+QString::number(params->getGraph()->getClocks().size()-1);
818     QString rstName = "ext_reset_"+QString::number(params->getGraph()->getClocks().size()-1);
819     fromIfaceClk = new GroupInterface(group,clkName, AbstractInterface::Input, AbstractInterface::Clock);
820     fromIfaceReset = new GroupInterface(group,rstName, AbstractInterface::Input, AbstractInterface::Reset);
821     group->addInterface(fromIfaceClk);
822     group->addInterface(fromIfaceReset);
823   // creating top group ext_clk iface item
824     GroupItem* groupItem = scene->getGroupItem();
825     InterfaceItem* fromIfaceItemClk = new InterfaceItem(0.5 , Parameters::West, fromIfaceClk, groupItem, params, true);
826     groupItem->addInterfaceItem(fromIfaceItemClk,true);
827     // creating top group ext_reset iface item
828     InterfaceItem* fromIfaceItemReset = new InterfaceItem(0.5 , Parameters::West, fromIfaceReset, groupItem, params, false);
829     groupItem->addInterfaceItem(fromIfaceItemReset,true);
830     // connecting ext_clk iface items
831     InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName("ext_clk");
832     if (toIfaceItemClk == NULL) {
833       cerr << "Abnormal case while connecting top group ext_clk to clkrstgen" << endl;
834     }
835     createConnection(context,fromIfaceItemClk, toIfaceItemClk, false);
836     // connecting ext_reset iface items
837     InterfaceItem* toIfaceItemReset = item->searchInterfaceItemByName("ext_reset");
838     if (toIfaceItemReset == NULL) {
839       cerr << "Abnormal case while connecting top group ext_reset to clkrstgen" << endl;
840     }
841     createConnection(context,fromIfaceItemReset, toIfaceItemReset, false);
842
843     params->blockToItem.insert(newOne,item);
844     params->unsaveModif = true;
845   }
846 }
847
848
849
850 GroupWidget *Dispatcher::createTopScene(Context context, double mainClock){
851   static QString fctName = "Dispatcher::createTopScene()";
852 #ifdef DEBUG_FCTNAME
853   cout << "call to " << qPrintable(fctName) << endl;
854 #endif
855
856   Graph* graph = NULL;
857   // creating the graph and thus, the topgroup
858   if (context == Design) {
859     graph = params->initGraph(true);
860     graph->addClock(mainClock);
861   }
862   else if (context == Load) {
863     graph = params->initGraph(false);
864   }
865
866   // get the top group
867   GroupBlock *topBlock = graph->getTopGroup();
868   // creating the top group widget
869   topGroupWidget = new GroupWidget(NULL,this,params);
870   currentGroupWidget = topGroupWidget;
871   // getting the newly created scene
872   GroupScene *scene = topGroupWidget->getScene();
873   scene->setId(sceneCounter++);
874   params->setTopScene(scene);
875   params->setCurrentScene(scene);
876   // creating the view part of the group
877   GroupItem *group = new GroupItem(NULL,topBlock,this,params);
878   // associate the top scene to the top group iten
879   scene->setGroupItem(group);
880
881   // adding the fake interface to the top group item
882   //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
883   //group->addInterface(item,true);
884
885
886   if (context == Design) {
887     // create clkrstgen
888     double freq = params->getGraph()->getClock(0);
889     params->getGraph()->resetClocks();
890     addClkRstGenBlock(context,freq);
891   }
892
893   groupList.append(topGroupWidget);
894   return topGroupWidget;
895 }
896
897 GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) {
898   static QString fctName = "Dispatcher::addNewEmptyGroup();";
899 #ifdef DEBUG_FCTNAME
900   cout << "call to " << qPrintable(fctName) << endl;
901 #endif
902   bool createIfaces = true;
903   if (context == Load) {
904     createIfaces = false;
905   }
906
907   // getting the parent block in the graph
908   GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
909   cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
910   GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent, createIfaces);
911   cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
912   // creating the BlockItem in the scene
913   BoxItem* newItem = scene->createBoxItem(groupBlock);
914
915   params->unsaveModif = true;
916
917   GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem);
918   if (show) child->show();
919   return child;
920
921 }
922
923 GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
924   static QString fctName = "Dispatcher::createChildScene()";
925 #ifdef DEBUG_FCTNAME
926   cout << "call to " << qPrintable(fctName) << endl;
927 #endif
928
929   GroupWidget* group = NULL;
930   /* NB: this method may be called during design process or when loading
931      a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
932      cannot be initialized yet. This is why there are 2 cases below
933    */
934
935   if (upperItemOfGroupItem != NULL) {
936     // getting back the goup block already created
937     GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
938     // creating the view part of the group
939     GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
940
941     // creating the group widget
942     group = new GroupWidget(parentWidget, this, params);
943     // getting the newly created scene
944     GroupScene *scene = group->getScene();
945     scene->setId(sceneCounter++);
946     // affecting group item to the scene
947     scene->setGroupItem(groupItem);
948     groupList.append(group);
949
950     mainWindow->getLibrary()->updateComboScene();
951   }
952   else {
953     GroupItem *groupItem = new GroupItem(this,params);
954     // creating the group widget
955     group = new GroupWidget(parentWidget, this, params);
956     // getting the newly created scene
957     GroupScene *scene = group->getScene();
958     // affecting group item to the scene
959     scene->setGroupItem(groupItem);
960     groupList.append(group);
961   }
962   return group;
963 }
964
965 void Dispatcher::destroyScene(Context context, GroupScene *scene) {
966   foreach(GroupScene* s, scene->getChildrenScene()) {
967     destroyScene(context, s);
968   }
969
970   if (scene->getNbChildScene() == 0) {
971     // remove scene from the parent list, if possible
972     if (scene->getParentScene() != NULL) {
973       scene->getParentScene()->removeChildScene(scene);
974     }
975     // destroy the GroupWidget
976     groupList.removeAll(scene->getGroupWidget());
977     scene->getGroupWidget()->deleteLater();
978   }
979   else {
980     cerr << "Abnormal case when destroying a scene" << endl;
981   }
982 }
983
984 void Dispatcher::showRaiseWindow(Context context, BoxItem *item) {
985   static QString fctName = "Dispatcher::showRaiseWindow()";
986 #ifdef DEBUG_FCTNAME
987   cout << "call to " << qPrintable(fctName) << endl;
988 #endif
989
990   cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
991   GroupItem* child = item->getChildGroupItem();
992   if (child == NULL) {
993     cerr << "abnormal case: child group item is null " << endl;
994     return;
995   }
996
997   GroupWidget* win = child->getScene()->getGroupWidget();
998
999   win->showNormal();
1000   win->raise();
1001   win->activateWindow();
1002
1003   currentGroupWidget = win;
1004   params->setCurrentScene(currentGroupWidget->getScene());
1005 }
1006
1007 void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) {
1008   static QString fctName = "Dispatcher::showRstClkIface()";
1009 #ifdef DEBUG_FCTNAME
1010   cout << "call to " << qPrintable(fctName) << endl;
1011 #endif
1012
1013   item->setRstClkVisible(!item->isRstClkVisible());
1014   
1015 }
1016
1017 void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) {
1018   static QString fctName = "Dispatcher::showWishboneIface()";
1019 #ifdef DEBUG_FCTNAME
1020   cout << "call to " << qPrintable(fctName) << endl;
1021 #endif
1022
1023   item->setWishboneVisible(!item->isWishboneVisible());  
1024 }
1025
1026 void Dispatcher::addNewFullGroup(Context context) {
1027   static QString fctName = "Dispatcher::addNewFullGroup()";
1028 #ifdef DEBUG_FCTNAME
1029   cout << "call to " << qPrintable(fctName) << endl;
1030 #endif
1031
1032
1033 #ifdef DEBUG_INCLFUN
1034
1035   QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
1036   QList<AbstractBlock*> listAbstractBlocks;   //abstract blocks in the group
1037   QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
1038
1039   /* What must be done:
1040      1 - creating a new GroupBlock
1041      2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
1042      3 - creating a BlockItem that references the new GroupBlock
1043      4 - creating a new GroupWidget
1044      5 - creating a new GroupItem added to the scene of the GroupWidget
1045
1046    */
1047
1048   /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
1049      associated to the GroupItem of the current scene
1050    */
1051   GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
1052   GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
1053   /* step 2: moving selected blocks */
1054   foreach(BlockItem* blockItem, listBlocks) {
1055     parentBlock->removeBlock(blockItem->getRefBlock());
1056     newGroupBlock->addBlock(blockItem->getRefBlock());
1057   }
1058
1059   GroupItem *parent = currentGroup->getScene()->getGroupItem();
1060   GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
1061   BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
1062   GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
1063
1064   //create the new window
1065   GroupWidget* win = new GroupWidget(this,params);
1066   win->getScene()->setGroupItem(groupItem);
1067   win->getScene()->addItem(groupItem);
1068   ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
1069   params->addWindow(win);
1070   win->show();
1071
1072   //add the new group
1073   params->getCurrentScene()->addBlockItem(blockItem);
1074   params->getCurrentScene()->addItem(blockItem);
1075   ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
1076
1077   //replace selected blocks in the group
1078   foreach(AbstractBoxItem *block, listBlocks){
1079     ((GroupItem*)block->getParentItem())->removeBlockItem(block);
1080     ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
1081     params->getCurrentScene()->removeItem(block);
1082     params->getCurrentScene()->removeBlockItem(block);
1083
1084     groupBlock->addBlock(block->getRefBlock());
1085     listAbstractBlocks.append(block->getRefBlock());
1086
1087     block->setUpperItem(groupItem);
1088     groupItem->addBlockItem(block);
1089     win->getScene()->addItem(block);
1090     win->getScene()->addBlockItem(block);
1091   }
1092
1093   //replace connection between selected blocks in the group
1094   foreach(ConnectionItem *conn, connections){
1095     if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
1096       if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
1097         parent->removeConnection(conn);
1098         params->getCurrentScene()->removeItem(conn);
1099
1100         groupItem->addConnection(conn);
1101         win->getScene()->addItem(conn);
1102       }
1103     }
1104   }
1105
1106   //create new interfaces and connections for the new group
1107   foreach(AbstractBoxItem *block, listBlocks){
1108     foreach(InterfaceItem *inter, block->getInterfaces()){
1109       cout << "inter : " << inter->getName().toStdString() << endl;
1110       if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
1111         cout << "connected from non null" << endl;
1112         if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
1113
1114           AbstractInterface *iface = inter->refInter->clone(0);
1115           iface->setName(iface->getName()+"_group");
1116           groupBlock->addInterface(iface);
1117
1118           InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1119           blockItem->addInterface(ifaceItem);
1120           blockItem->resetInterfacesPosition();
1121
1122           InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
1123           groupItem->addInterface(ifaceGroupItem);
1124           groupItem->resetInterfacesPosition();
1125           foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1126             if(conn->getToInterfaceItem() == inter){
1127               conn->setToInterfaceItem(ifaceItem);
1128               ifaceItem->refInter->setConnectedFrom(NULL);
1129               conn->getFromInterfaceItem()->refInter->clearConnectedTo();
1130               connect(ifaceItem,conn->getFromInterfaceItem());
1131             }
1132           }
1133           params->setCurrentWindow(win);
1134
1135           inter->refInter->setConnectedFrom(NULL);
1136           ifaceGroupItem->refInter->clearConnectedTo();
1137           connect(inter,ifaceGroupItem);
1138           params->setCurrentWindow(mainWindow);
1139         }
1140       }
1141
1142       if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
1143         cout << "connected to non null" << endl;
1144         foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
1145           if(!listAbstractBlocks.contains(iface->getOwner())){
1146
1147             AbstractInterface *iface = inter->refInter->clone(0);
1148             iface->setName(iface->getName()+"_group");
1149             groupBlock->addInterface(iface);
1150
1151             InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1152             blockItem->addInterface(ifaceItem);
1153             blockItem->resetInterfacesPosition();
1154
1155             foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1156               if(conn->getFromInterfaceItem() == inter){
1157                 conn->setFromInterfaceItem(ifaceItem);
1158                 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
1159                 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
1160               }
1161             }
1162
1163             InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
1164             groupItem->addInterface(ifaceGroupItem);
1165             groupItem->resetInterfacesPosition();
1166             inter->refInter->clearConnectedTo();
1167             ifaceGroupItem->refInter->setConnectedFrom(NULL);
1168             connect(ifaceGroupItem,inter);
1169           }
1170         }
1171       }
1172     }
1173   }
1174
1175   //update window
1176
1177   parent->updateShape();
1178   currentGroup->getScene()->updateConnectionItemsShape();
1179   currentGroup = win;
1180   groupItem->updateShape();
1181   win->getScene()->updateConnectionItemsShape();
1182   groupItem->update(groupItem->boundingRect());
1183
1184 #endif
1185 }
1186
1187 void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
1188   static QString fctName = "Dispatcher::removeBoxItem()";
1189 #ifdef DEBUG_FCTNAME
1190   cout << "call to " << qPrintable(fctName) << endl;
1191 #endif
1192   /* NB: only called in Design context */
1193   if (context != Design) {
1194     cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl;
1195     return;
1196   }
1197
1198   /* a BoxItem (group of func) can be removed only if none of its
1199      interfaces is connected to a group interface that is itself
1200      connected to another one.
1201   */
1202   bool canRemove = true;
1203
1204   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1205     foreach(ConnectionItem* conn, ifaceItem->connections) {
1206       InterfaceItem* other = NULL;
1207       if (conn->getFromInterfaceItem() == ifaceItem) {
1208         other = conn->getToInterfaceItem();
1209       }
1210       else {
1211         other = conn->getFromInterfaceItem();
1212       }
1213
1214       if (other->getOwner()->isGroupItem()) {
1215         ConnectedInterface* ref = other->refInter;
1216         if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1217           canRemove = false;
1218         }
1219       }
1220     }
1221   }
1222   if (!canRemove) {
1223     QMessageBox::warning(NULL,"Forbidden operation",
1224                          "The block has at least one connection to a group interface that is totally connected.",
1225                          QMessageBox::Ok);
1226     return;
1227   }
1228
1229   QString msg = "";
1230   if (item->getRefBlock()->isFunctionalBlock()) {
1231     msg = "Removing block ";
1232   }
1233   else {
1234      msg = "Removing group ";
1235   }
1236   msg += item->getRefBlock()->getName();
1237   msg += " and all its connections.\n\nAre you sure ?";
1238
1239   int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1240   if (ret == QMessageBox::Cancel) {
1241     return;
1242   }
1243   removeAllBlockConnections(context, item);
1244
1245   if (item->getRefBlock()->isFunctionalBlock()) {
1246     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());    
1247     item->getScene()->removeBoxItem(item);
1248     params->getGraph()->removeFunctionalBlock(block);
1249     params->blockToItem.remove(block);
1250
1251   }
1252   else if (item->getRefBlock()->isGroupBlock()) {
1253
1254     GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1255
1256     // remove all child scenes recursively
1257     GroupItem* subgroup = item->getChildGroupItem();
1258     destroyScene(context, subgroup->getScene());
1259     // remove the BoxItem
1260     item->getScene()->removeBoxItem(item);
1261     // remove the group from the graph
1262     params->getGraph()->removeGroupBlock(group);
1263   }
1264 }
1265
1266 void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) {
1267   static QString fctName = "Dispatcher::removeAllBlockConnection()";
1268 #ifdef DEBUG_FCTNAME
1269   cout << "call to " << qPrintable(fctName) << endl;
1270 #endif
1271   /* NB: only called in Design context */
1272   if (context != Design) {
1273     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1274     return;
1275   }
1276
1277   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1278     foreach(ConnectionItem* conn, ifaceItem->connections) {
1279       removeConnection(context, conn);
1280     }
1281   }
1282 }
1283
1284 void Dispatcher::removeStimuliItem(Context context, StimuliItem *item) {
1285   static QString fctName = "Dispatcher::removeStimuliItem()";
1286 #ifdef DEBUG_FCTNAME
1287   cout << "call to " << qPrintable(fctName) << endl;
1288 #endif
1289   /* NB: only called in Design context */
1290   if (context != Design) {
1291     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1292     return;
1293   }
1294   
1295   QString msg = "Removing stimmuli ";
1296   
1297   msg += item->getRefBlock()->getName();
1298   msg += " and all its connections.\n\nAre you sure ?";
1299
1300   int ret = QMessageBox::question(NULL,"Removing stimuli block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1301   if (ret == QMessageBox::Cancel) {
1302     return;
1303   }
1304   removeAllBlockConnections(context, item);
1305   
1306   FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());  
1307   item->getScene()->removeStimuliItem(item);
1308   params->getGraph()->removeStimuliBlock(block);
1309 }
1310
1311
1312 void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
1313   static QString fctName = "Dispatcher::removeConnection()";
1314 #ifdef DEBUG_FCTNAME
1315   cout << "call to " << qPrintable(fctName) << endl;
1316 #endif
1317   /* NB: only called in Design context */
1318   if (context != Design) {
1319     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1320     return;
1321   }
1322
1323   InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1324   InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1325
1326 #ifdef DEBUG
1327   cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1328 #endif
1329
1330   InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1331   GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1332
1333   ConnectedInterface *fromInter = fromIfaceItem->refInter;
1334   ConnectedInterface *toInter = toIfaceItem->refInter;  
1335   
1336   // test if one of the interface bounded to item is owned by a GroupItem
1337   if (fromIfaceItem->getOwner()->isGroupItem()) {
1338     groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1339     groupIfaceItem = fromIfaceItem;    
1340   }
1341   else if (toIfaceItem->getOwner()->isGroupItem()) {
1342     groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1343     groupIfaceItem = toIfaceItem;    
1344   }
1345   else {
1346     groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1347   }
1348
1349   // removing the connection from graph
1350 #ifdef DEBUG
1351   cout << "removing connections from graph ..." ;
1352 #endif  
1353   fromInter->disconnectTo(toInter);
1354   
1355 #ifdef DEBUG
1356   cout << "done." << endl ;
1357 #endif
1358
1359   // removing the connection from scene
1360 #ifdef DEBUG
1361   cout << "removing connections from scene ..." ;
1362 #endif  
1363   groupItem->getScene()->removeConnectionItem(connItem);
1364
1365 #ifdef DEBUG
1366   cout << "done." << endl ;
1367 #endif
1368   
1369   // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1370   if (groupIfaceItem != NULL) {
1371     
1372     // determine if the interface must be removed since it has no more connections.
1373     bool groupInterRemove = false;
1374     if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1375     
1376     if (groupInterRemove) {
1377       // get the GroupInterface from interface item
1378       ConnectedInterface* groupInter = groupIfaceItem->refInter;            
1379       // remove interface from GroupItem, and delete it.
1380       groupItem->removeInterfaceItem(groupIfaceItem);      
1381       // get the parent BoxItem of GroupItem if it exists.
1382       BoxItem* parent2Item = groupItem->getParentItem();
1383       if (parent2Item != NULL) {
1384         InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1385         // remove interface intem in parent BoxItem
1386         parent2Item->removeInterfaceItem(group2IfaceItem);
1387       }
1388       // remove GroupInterface in the graph.
1389       groupInter->getOwner()->removeInterface(groupInter);
1390     }
1391   }
1392 }
1393
1394 void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clkName, int idGen) throw(Exception) {
1395
1396   static QString fctName = "Dispatcher::connectBoxItemClock()";
1397 #ifdef DEBUG_FCTNAME
1398   cout << "call to " << qPrintable(fctName) << endl;
1399 #endif
1400   /* NB: only called in Design context */
1401   if (context != Design) {
1402     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1403     return;
1404   }
1405
1406   InterfaceItem* fromIfaceItemClk = NULL;
1407   InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName);
1408   GroupItem* parentGroup = item->getScene()->getGroupItem();
1409   BoxItem* clkrstItem = NULL;
1410
1411   if (parentGroup->getRefBlock()->isTopGroupBlock()) {
1412     QString genName = "clkrstgen_" + QString::number(idGen);
1413     clkrstItem = item->getScene()->searchBoxItemByName(genName);
1414     if (clkrstItem == NULL) {
1415       throw(Exception(IFACE_TOP_NOCLKRSTGEN));
1416     }
1417     else {
1418       fromIfaceItemClk = clkrstItem->searchInterfaceItemByName("clk");
1419     }
1420     cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to clk of " << qPrintable(genName) << endl;
1421   }
1422   else {
1423     // searching for ext_clk_idGen
1424     QString name = "ext_clk_"+QString::number(idGen);
1425     fromIfaceItemClk = parentGroup->searchInterfaceItemByName(name);
1426     cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to " << qPrintable(name) << " of parent group " << qPrintable(parentGroup->getRefBlock()->getName()) << endl;
1427   }
1428
1429   if (fromIfaceItemClk == NULL) {
1430     throw(Exception(IFACE_GROUP_NOCLKRST));
1431   }
1432   else {
1433     createConnection(context, fromIfaceItemClk, toIfaceItemClk, false);
1434     cout << "connection done."  << endl;
1435   }
1436 }
1437
1438 void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rstName, int idGen) throw(Exception) {
1439
1440   static QString fctName = "Dispatcher::connectBoxItemReset()";
1441 #ifdef DEBUG_FCTNAME
1442   cout << "call to " << qPrintable(fctName) << endl;
1443 #endif
1444   /* NB: only called in Design context */
1445   if (context != Design) {
1446     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1447     return;
1448   }
1449
1450   InterfaceItem* fromIfaceItemRst = NULL;
1451   InterfaceItem* toIfaceItemRst = item->searchInterfaceItemByName(rstName);
1452   GroupItem* parentGroup = item->getScene()->getGroupItem();
1453   BoxItem* clkrstItem = NULL;
1454
1455   if (parentGroup->getRefBlock()->isTopGroupBlock()) {
1456     QString genName = "clkrstgen_" + QString::number(idGen);
1457     clkrstItem = item->getScene()->searchBoxItemByName(genName);
1458     if (clkrstItem == NULL) {
1459       throw(Exception(IFACE_TOP_NOCLKRSTGEN));
1460     }
1461     else {
1462       fromIfaceItemRst = clkrstItem->searchInterfaceItemByName("reset");
1463     }
1464     cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to reset of " << qPrintable(genName) << endl;
1465   }
1466   else {
1467     // searching for ext_rst_idGen
1468     QString name = "ext_rst_"+QString::number(idGen);
1469     fromIfaceItemRst = parentGroup->searchInterfaceItemByName(name);
1470     cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to " << qPrintable(name) << " of parent group " << qPrintable(parentGroup->getRefBlock()->getName()) << endl;
1471   }
1472
1473   if (fromIfaceItemRst == NULL) {
1474     throw(Exception(IFACE_GROUP_NOCLKRST));
1475   }
1476   else {
1477     createConnection(context, fromIfaceItemRst, toIfaceItemRst, false);
1478     cout << "connection done."  << endl;
1479   }
1480 }
1481
1482 void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QString clkName, int idGen) throw(Exception) {
1483
1484   static QString fctName = "Dispatcher::connectStimuliItemClock()";
1485 #ifdef DEBUG_FCTNAME
1486   cout << "call to " << qPrintable(fctName) << endl;
1487 #endif
1488   /* NB: only called in Design context */
1489   if (context != Design) {
1490     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1491     return;
1492   }
1493
1494   InterfaceItem* fromIfaceItemClk = NULL;
1495   InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName);
1496   BoxItem* clkrstItem = NULL;
1497
1498   QString genName = "clkrstgen_" + QString::number(idGen);
1499   clkrstItem = item->getScene()->searchBoxItemByName(genName);
1500   if (clkrstItem == NULL) {
1501     throw(Exception(IFACE_TOP_NOCLKRSTGEN));
1502   }
1503   else {
1504     fromIfaceItemClk = clkrstItem->searchInterfaceItemByName("clk");
1505   }
1506   cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to clock of " << qPrintable(genName) << endl;
1507
1508   if (fromIfaceItemClk == NULL) {
1509     throw(Exception(IFACE_GROUP_NOCLKRST));
1510   }
1511   else {
1512     createConnection(context, fromIfaceItemClk, toIfaceItemClk, false);
1513     cout << "connection done."  << endl;
1514   }
1515 }
1516
1517 void Dispatcher::connectStimuliItemReset(Context context, StimuliItem *item, QString rstName, int idGen) throw(Exception) {
1518   static QString fctName = "Dispatcher::connectStimuliItemReset()";
1519 #ifdef DEBUG_FCTNAME
1520   cout << "call to " << qPrintable(fctName) << endl;
1521 #endif
1522   /* NB: only called in Design context */
1523   if (context != Design) {
1524     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1525     return;
1526   }
1527
1528   InterfaceItem* fromIfaceItemRst = NULL;
1529   InterfaceItem* toIfaceItemRst = item->searchInterfaceItemByName(rstName);
1530   BoxItem* clkrstItem = NULL;
1531
1532   QString genName = "clkrstgen_" + QString::number(idGen);
1533   clkrstItem = item->getScene()->searchBoxItemByName(genName);
1534   if (clkrstItem == NULL) {
1535     throw(Exception(IFACE_TOP_NOCLKRSTGEN));
1536   }
1537   else {
1538     fromIfaceItemRst = clkrstItem->searchInterfaceItemByName("reset");
1539   }
1540   cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to reset of " << qPrintable(genName) << endl;
1541
1542   if (fromIfaceItemRst == NULL) {
1543     throw(Exception(IFACE_GROUP_NOCLKRST));
1544   }
1545   else {
1546     createConnection(context, fromIfaceItemRst, toIfaceItemRst, false);
1547     cout << "connection done."  << endl;
1548   }
1549 }
1550
1551
1552 void Dispatcher::showBlocksLibrary(){
1553   cout << "showing block library" << endl;
1554   mainWindow->getLibrary()->show();
1555   mainWindow->getLibrary()->raise();
1556 }
1557
1558 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
1559
1560   static QString fctName = "Dispatcher::showProperties()";
1561 #ifdef DEBUG_FCTNAME
1562   cout << "call to " << qPrintable(fctName) << endl;
1563 #endif
1564   /* NB: only called in Design context */
1565   if (context != Design) {
1566     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1567     return;
1568   }
1569
1570   QDialog* dial = new InterfacePropertiesDialog(inter);
1571   dial->exec();
1572 }
1573
1574 /* connectInterToGroup() :
1575    The only way for a block (functional of group) within a GroupItem to be connected
1576    to the latter is to right-click on one of its interfaces and to choose "connect to group".
1577    That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1578    interfaces.
1579 */
1580 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
1581
1582   static QString fctName = "Dispatcher::connectInterToGroup()";
1583 #ifdef DEBUG_FCTNAME
1584   cout << "call to " << qPrintable(fctName) << endl;
1585 #endif
1586   /* NB: only called in Design context */
1587   if (context != Design) {
1588     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1589     return;
1590   }
1591
1592   // getting the GroupBlock and GroupItem that are parent of the block that owns item
1593   ConnectedInterface *refInter = item->refInter;
1594   cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1595   GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1596   cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1597   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1598
1599   // creating/adding the group interface in the graph model
1600   GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());  
1601   parentItem->getRefBlock()->addInterface(groupInter);
1602   // creating/adding the group control interface in the graph model if the purpose is data
1603   if (refInter->getPurpose() == AbstractInterface::Data) {
1604     GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1605     groupCtlInter->setAssociatedIface(groupInter);
1606     parentItem->getRefBlock()->addInterface(groupCtlInter);
1607   }
1608   // creating/adding the group interface in the current scene model, and connection item
1609   InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1610   parentItem->addInterfaceItem(groupIfaceItem,true);
1611
1612   // creating the connection, in graph and with an item
1613   /* NOTE:
1614      Since the group interface is for now unconnected, it is impossible to determine
1615      its clock domain. Thus, the connection must be created without testing the clock domain
1616      consistency. For that, we cheat by changing the context to Load because it implies no clock test.
1617    */
1618   createConnection(Load, item, groupIfaceItem);
1619
1620   // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1621   BoxItem* parent2Item = parentItem->getParentItem();
1622   if(parent2Item != NULL){
1623     InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1624     parent2Item->addInterfaceItem(blockIfaceItem,true);
1625   }
1626
1627
1628   parentItem->getScene()->updateConnectionItemsShape();
1629   unselectAllItems(context);
1630   params->unsaveModif = true;
1631 }
1632
1633 void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) {
1634   static QString fctName = "Dispatcher::removeBlockInterface()";
1635 #ifdef DEBUG_FCTNAME
1636   cout << "call to " << qPrintable(fctName) << endl;
1637 #endif
1638   /* NB: only called in Design context */
1639   if (context != Design) {
1640     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1641     return;
1642   }
1643
1644   /* first, remove all connections from item
1645      NB:  if there is a connection to a group interface, then this
1646      method should not be called if the group interface is also
1647      connected to another interface. Normally, this is not possible
1648      because such a check is done when creating the contextual menu
1649      that allows to remove an interface.
1650    */
1651   foreach(ConnectionItem* conn, item->connections) {
1652     removeConnection(context, conn);
1653   }
1654
1655   ConnectedInterface* ref = item->refInter;
1656   item->getOwner()->removeInterfaceItem(item);
1657   FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1658   fun->removeInterface(ref);
1659 }
1660
1661 void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
1662   static QString fctName = "Dispatcher::removeGroupInterface()";
1663 #ifdef DEBUG_FCTNAME
1664   cout << "call to " << qPrintable(fctName) << endl;
1665 #endif
1666   /* NB: only called in Design context */
1667   if (context != Design) {
1668     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1669     return;
1670   }
1671
1672   /* NB: just remove all connections from/to this item, since when there are no more
1673      ones to a GroupItem, it is automatically deleted.
1674    */
1675   foreach(ConnectionItem* conn, item->connections) {
1676     removeConnection(context, conn);
1677   }
1678 }
1679
1680 QMap<int, QString> Dispatcher::getAllGroupNames() {
1681
1682   QMap<int, QString> list;
1683   foreach(GroupWidget *group, groupList) {
1684     list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1685   }
1686   return list;
1687 }
1688
1689 GroupScene* Dispatcher::getSceneById(int id) {
1690   foreach(GroupWidget *group, groupList){
1691     if(group->getScene()->getId() == id)
1692       return group->getScene();
1693   }
1694   cout << "search scene by id :" << id << " :: not found..." << endl;
1695   return NULL;
1696 }
1697
1698 GroupItem *Dispatcher::getGroupItemById(int id) {
1699   foreach(GroupWidget *group, groupList) {
1700     GroupScene* scene = group->getScene();
1701     if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1702   }
1703   cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1704   return NULL;
1705 }
1706
1707 BoxItem *Dispatcher::getBoxItemById(int id) {
1708   foreach(GroupWidget *group, groupList) {
1709
1710     GroupScene* scene = group->getScene();
1711     foreach(BoxItem *item, scene->getBoxItems()){
1712       if(item->getId() == id){
1713           return item;
1714       }
1715     }
1716   }
1717   cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1718   return NULL;
1719 }
1720
1721 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1722
1723   foreach(GroupWidget *group, groupList) {
1724
1725     GroupScene* scene = group->getScene();
1726
1727     foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1728       if(item->getId() == id){
1729         return item;
1730       }
1731     }
1732     foreach(BoxItem *block, scene->getBoxItems()){
1733       foreach(InterfaceItem *item, block->getInterfaces()){
1734         if(item->getId() == id){
1735           return item;
1736         }
1737       }
1738     }
1739   }
1740   cout << "search interface by id :" << id << " :: not found..." << endl;
1741   return NULL;
1742 }
1743
1744 void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) {
1745   static QString fctName = "Dispatcher::findGraphModifications()";
1746 #ifdef DEBUG_FCTNAME
1747   cout << "call to " << qPrintable(fctName) << endl;
1748 #endif
1749   /* NB: only called in Design context */
1750   if (context != Design) {
1751     cout << "Abnormal case: call to " <<qPrintable(fctName) << " not in Design context" << endl;
1752     return;
1753   }
1754
1755   block->computeAdmittanceDelays();
1756   // get the block item that is associated to block
1757   BoxItem* toBlockItem = params->blockToItem.value(block);
1758
1759   /* VERSION 1: just add delays if needed */
1760   QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1761   QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1762   while (iterD.hasNext()) {
1763     iterD.next();
1764     QList<int>* delay = iterD.value();
1765     if (delay->at(0) > 0) {
1766       // create delay and associate it to the connected input
1767
1768       ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1769       AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1770       cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1771       toIface->setInputModifier(mod);
1772       // repaint
1773       toBlockItem->update();
1774     }
1775   }
1776 }
1777