1 #include "Dispatcher.h"
2 #include "Parameters.h"
3 #include "MainWindow.h"
5 #include "ExternalResource.h"
8 #include "ReferenceBlock.h"
9 #include "GroupBlock.h"
10 #include "FunctionalBlock.h"
12 #include "ConnectedInterface.h"
13 #include "ReferenceInterface.h"
14 #include "GroupInterface.h"
15 #include "FunctionalInterface.h"
17 #include "GroupWidget.h"
18 #include "GroupScene.h"
19 #include "GroupItem.h"
21 #include "SourceItem.h"
22 #include "InterfaceItem.h"
23 #include "ConnectionItem.h"
25 #include "BlockLibraryWidget.h"
26 #include "BlockLibraryTree.h"
28 #include "AbstractInputModifier.h"
29 #include "DelayInputModifier.h"
32 #include "InterfacePropertiesDialog.h"
34 #include <QHashIterator>
36 int Dispatcher::sceneCounter = 0;
38 Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
41 params->setDispatcher(this);
42 currentGroupWidget = NULL;
43 topGroupWidget = NULL;
46 GroupWidget *Dispatcher::loadProject(const QString& filename) {
50 root = params->openProjectFile(filename);
52 catch(Exception err) {
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();
63 params->setTopScene(scene);
64 params->setCurrentScene(scene);
67 topGroupWidget = params->loadProject(root);
70 cerr << qPrintable(e.getDefaultMessage()) << endl;
71 cerr << "Aborting ..." << endl;
72 // TO DO : deleteting topGroup and all
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;
84 void Dispatcher::closeCurrentProject() {
86 foreach(GroupWidget* win, groupList) {
90 params->destroyGraph();
91 topGroupWidget = NULL;
92 currentGroupWidget = NULL;
96 void Dispatcher::setSceneCounter(Context context, int value) {
98 if (context != Load) return;
102 bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
104 ConnectedInterface* ref1 = iface1->refInter;
105 ConnectedInterface* ref2 = iface2->refInter;
106 // connect both interface
111 // test the ref1->ref2 connection
112 if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
113 ref1->connectTo(ref2);
116 // if the first one did not work, test ref2->ref1
117 if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {
118 ref2->connectTo(ref1);
121 if ((ok1 == true) || (ok2 == true)) {
123 iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
125 unselectAllItems(context);
126 params->unsaveModif = true;
127 cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl;
134 void Dispatcher::unselectAllItems(Context context, int direction){
136 GroupScene *scene = params->getCurrentScene();
138 foreach(BoxItem* block, scene->getBoxItems()) {
139 block->setSelected(false);
140 block->setCurrentInterface(NULL);
142 scene->unselecteInterfaces();
146 void Dispatcher::setCurrentGroupWidget(Context context, GroupWidget *win){
148 win->changeConnectionMode(-1);
149 currentGroupWidget = win;
150 params->setCurrentScene(win->getScene());
153 void Dispatcher::changeConnectionMode(Context context, int mode){
156 foreach(GroupWidget* win, groupList){
158 QToolButton* buttonNewConnection = win->getButtonNewConnection();
160 QPalette pal = buttonNewConnection->palette();
163 if(params->sceneMode != Parameters::EditOnConnection){
164 params->sceneMode = Parameters::EditOnConnection;
165 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
167 params->sceneMode = Parameters::EditNoOperation;
168 pal.setColor(QPalette::Button, QColor("#edeceb"));
171 else if(mode == Parameters::EditOnConnection){
172 params->sceneMode = Parameters::EditOnConnection;
173 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
176 params->sceneMode = Parameters::EditNoOperation;
177 pal.setColor(QPalette::Button, QColor("#edeceb"));
179 unselectAllInterfaces();
181 buttonNewConnection->setAutoFillBackground(true);
182 buttonNewConnection->setPalette(pal);
183 buttonNewConnection->update();
188 void Dispatcher::generateVHDL(Context context) throw(Exception) {
189 static QString fctName = "Dispatcher::generateVHDL()";
191 cout << "call to " << qPrintable(fctName) << endl;
194 QDir baseDir(params->projectPath);
195 QDir srcDir(params->projectPath+"/src");
197 if (!baseDir.exists()) {
198 cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl;
202 if (srcDir.exists()) {
203 srcDir.removeRecursively();
205 baseDir.mkdir("src");
207 if (! baseDir.exists("testbench")) {
208 baseDir.mkdir("testbench");
210 if (! baseDir.exists("Makefile")) {
211 QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim");
212 QString dest = params->projectPath;
217 // copying external resources
218 QString dest = params->projectPath;
221 params->getGraph()->generateVHDL(dest);
223 QList<QString> extResources = params->getGraph()->getExternalResources();
224 foreach(QString name, extResources) {
225 cout << qPrintable(name) << endl;
226 QList<ExternalResource*> lstRes = params->searchResourceByName(name);
227 foreach(ExternalResource* res, lstRes) {
228 QFile resFile(res->getFile());
229 QFileInfo info(res->getFile());
230 QString destFile = dest+info.fileName();
231 cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl;
232 resFile.copy(destFile);
240 // creating parameters file
241 QString paramName = params->projectPath+"/params-isim.txt";
242 QFile paramFile(paramName);
243 if (!paramFile.open(QIODevice::WriteOnly)) {
244 throw(Exception(PROJECTPATH_NOACCESS));
246 QTextStream out(¶mFile);
247 out << "PROJECT_NAME := " << params->projectName << endl << endl;
248 out << "SRC_DIR := src" << endl;
249 out << "TB_DIR := testbench" << endl << endl;
250 out << "VHDL_SRC := ";
253 srcDir.setNameFilters(filter);
254 QStringList listVHDL = srcDir.entryList();
255 for(int j=0;j<listVHDL.size();j++) {
259 out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j));
260 if (j != listVHDL.size()-1) {
266 out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl;
267 out << "TB_SRC := $(TB_DIR)/read_csv.vhd \\" << endl;
268 out << "\t$(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl;
269 out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl;
273 QString msg = "VHDL generation completed successfully. Go to ";
274 msg += params->projectPath+" and type the following commands to launch a simulation:\n";
275 msg += "\tmake clean\n";
277 msg += "\tmake view\n";
278 QMessageBox::information(mainWindow,"VHDL generation", msg, QMessageBox::Ok);
282 void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){
283 static QString fctName = "Dispatcher::generateBlockVHDL()";
285 cout << "call to " << qPrintable(fctName) << endl;
288 if (item->getRefBlock()->isFunctionalBlock()) {
289 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
291 block->generateVHDL(params->projectPath);
294 cout << qPrintable(e.getMessage()) << endl;
299 void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){
300 static QString fctName = "Dispatcher::renameFunctionalBlock()";
302 cout << "call to " << qPrintable(fctName) << endl;
305 GroupWidget* win = item->getScene()->getGroupWidget();
310 text = QInputDialog::getText(win, "Rename a functional block",
311 "New name:", QLineEdit::Normal,
312 item->getRefBlock()->getName(), &ok);
315 if (text == item->getRefBlock()->getName()) return;
317 if( (text.isEmpty()) || (text.length() > 30)) {
318 QMessageBox::warning(win,"Error in given name",
319 "the block name must be shorter than 30 characters, cannot be empty",
324 FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
326 QMessageBox::warning(win,"Error in given name",
327 "the name provided is similar to that of another functional block within the group",
334 item->getRefBlock()->setName(text);
338 void Dispatcher::renameGroupBlock(Context context, GroupItem *item){
339 static QString fctName = "Dispatcher::renameGroupBlock()";
341 cout << "call to " << qPrintable(fctName) << endl;
344 GroupWidget* win = item->getScene()->getGroupWidget();
349 text = QInputDialog::getText(win, "Rename a group",
350 "New name:", QLineEdit::Normal,
351 item->getRefBlock()->getName(), &ok);
354 if (text == item->getRefBlock()->getName()) return;
356 if( (text.isEmpty()) || (text.length() > 30)) {
357 QMessageBox::warning(win,"Error in given name",
358 "the block name must be shorter than 30 characters, cannot be empty",
363 GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
365 QMessageBox::warning(win,"Error in given name",
366 "the name provided is similar to that of another group",
373 item->getRefBlock()->setName(text);
374 if(item->getScene()->getGroupWidget()->isTopGroup()) {
375 mainWindow->setWindowTitle("blast - "+text);
378 item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
381 mainWindow->getLibrary()->updateComboScene();
384 void Dispatcher::renameSourceBlock(Context context, SourceItem *item){
385 static QString fctName = "Dispatcher::renameSourceBlock()";
387 cout << "call to " << qPrintable(fctName) << endl;
390 GroupWidget* win = item->getScene()->getGroupWidget();
395 text = QInputDialog::getText(win, "Rename a source",
396 "New name:", QLineEdit::Normal,
397 item->getRefBlock()->getName(), &ok);
400 if (text == item->getRefBlock()->getName()) return;
402 if( (text.isEmpty()) || (text.length() > 30)) {
403 QMessageBox::warning(win,"Error in given name",
404 "the block name must be shorter than 30 characters, cannot be empty",
409 FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
411 QMessageBox::warning(win,"Error in given name",
412 "the name provided is similar to that of another source block within the top group",
419 item->getRefBlock()->setName(text);
424 void Dispatcher::renameInterface(Context context, InterfaceItem *item) {
425 static QString fctName = "Dispatcher::renameInterface()";
427 cout << "call to " << qPrintable(fctName) << endl;
430 GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
435 text = QInputDialog::getText(win, "Rename an interface",
436 "New name:", QLineEdit::Normal,
437 item->refInter->getName(), &ok);
441 if (text == item->refInter->getName()) return;
443 if( (text.isEmpty()) || (text.length() > 30)) {
444 QMessageBox::warning(win,"Error in given name",
445 "the interface name must be shorter than 30 characters, cannot be empty",
450 AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
452 QMessageBox::warning(win,"Error in given name",
453 "the name provided is similar to that of another interface",
459 item->refInter->setName(text);
460 AbstractInterface* assoIface = item->refInter->getAssociatedIface();
461 if (assoIface != NULL) {
462 assoIface->setName(text+"_enb");
464 item->updateName(text);
465 item->getOwner()->nameChanged();
468 void Dispatcher::showPatterns(Context context, InterfaceItem *item) {
469 static QString fctName = "Dispatcher::showPatterns()";
471 cout << "call to " << qPrintable(fctName) << endl;
474 if (item->refInter->getDirection() == AbstractInterface::Input) {
475 msg = "Input pattern of iface ";
476 msg += item->refInter->getName();
478 msg += item->refInter->getOwner()->getName();
480 // get the precursor output pattern
481 ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
482 QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
484 AbstractInputModifier* modifier = connIface->getInputModifier();
485 // check if the input is modified
486 if (modifier != NULL) {
488 out = modifier->getModifiedInput(out);
491 foreach(char c, *out) {
492 msg += QString::number((int)c);
496 else if (item->refInter->getDirection() == AbstractInterface::Output) {
497 msg = "Output pattern of iface ";
498 msg += item->refInter->getName();
500 msg += item->refInter->getOwner()->getName();
502 ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
503 if (iface->getOutputPattern() == NULL) return;
504 foreach(char c, *(iface->getOutputPattern())) {
505 msg += QString::number((int)c);
509 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
512 void Dispatcher::showModifier(Context context, InterfaceItem *item) {
513 static QString fctName = "Dispatcher::showModifier()";
515 cout << "call to " << qPrintable(fctName) << endl;
518 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
519 AbstractInputModifier* mod = assoIface->getInputModifier();
520 if (mod->isDelay()) {
521 DelayInputModifier* delay = (DelayInputModifier *)mod;
522 msg = "Pattern of iface ";
523 msg += item->refInter->getName();
525 msg += item->refInter->getOwner()->getName();
526 msg += " is modified by a simple delay of ";
527 msg += QString::number(delay->getDelayLength());
530 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
533 void Dispatcher::removeModifier(Context context, InterfaceItem *item) {
534 static QString fctName = "Dispatcher::showModifier()";
536 cout << "call to " << qPrintable(fctName) << endl;
539 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
540 assoIface->clearInputModifier();
544 void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){
545 static QString fctName = "Dispatcher::duplicateBoxItem()";
547 cout << "call to " << qPrintable(fctName) << endl;
550 GroupScene *scene = item->getScene();
551 AbstractBlock* block = item->getRefBlock();
552 AbstractBlock *newBlock;
554 // only duplicate functional blocks
555 if(block->isFunctionalBlock()) {
557 // adding to the model
558 FunctionalBlock* funBlock = (FunctionalBlock*)block;
559 newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
560 // adding to the view
561 scene->createBoxItem(newBlock);
563 params->unsaveModif = true;
567 void Dispatcher::duplicateSourceItem(Context context, SourceItem *item) {
568 static QString fctName = "Dispatcher::duplicateSourceItem()";
570 cout << "call to " << qPrintable(fctName) << endl;
573 GroupScene *scene = item->getScene();
574 AbstractBlock* block = item->getRefBlock();
575 AbstractBlock *newBlock;
577 // only duplicate functional blocks
578 if(block->isFunctionalBlock()) {
580 // adding to the model
581 FunctionalBlock* funBlock = (FunctionalBlock*)block;
582 newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
583 // adding to the view
584 scene->createSourceItem(newBlock);
586 params->unsaveModif = true;
590 void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) {
591 static QString fctName = "Dispatcher::duplicateInterfaceItem()";
593 cout << "call to " << qPrintable(fctName) << endl;
596 AbstractInterface *refI = item->refInter;
597 if (! refI->isFunctionalInterface()) return;
599 AbstractBlock *refB = refI->getOwner();
600 if(! refB->isFunctionalBlock()) return;
602 FunctionalInterface* iface = (FunctionalInterface*)refI;
603 AbstractInterface *cloneIface = iface->clone();
604 if (cloneIface == NULL) {
605 QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
609 refB->addInterface(cloneIface);
611 InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
612 item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
614 // creating control interface if needed
615 if (refI->getAssociatedIface() != NULL) {
616 QString ctlName = cloneIface->getName()+"_enb";
617 ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
618 refB->addInterface(ctlIface);
619 if (! ctlIface->setAssociatedIface(cloneIface)) {
620 cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
626 BoxItem* Dispatcher::addBlock(Context context, int idCategory, int idBlock, int idScene, QHash<QString, int> clkRstToGen) {
627 static QString fctName = "Dispatcher::addBlock()";
629 cout << "call to " << qPrintable(fctName) << endl;
631 bool newSource = false;
632 BoxItem* item = NULL;
634 /* For now, this method is only used while designing and not loading */
635 if (context == Design) {
636 GroupScene *scene = getSceneById(idScene);
637 ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
638 // if block has no inputs, propose to add it as a source to top scene
639 if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
640 int ret = QMessageBox::question(NULL,"Adding a block to top scene","Selected block may be used as a source for the top scene. Do you want to add it as a source ?");
641 if (ret == QMessageBox::Yes) {
646 FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref, true);
647 scene->createSourceItem(newOne);
651 GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
652 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true);
654 // creating the box item
655 item = scene->createBoxItem(newOne);
656 if (params->autoConnMainClk) {
657 // for now just use the first one
658 QHashIterator<QString,int> iter(clkRstToGen);
659 while (iter.hasNext()) {
661 AbstractInterface* iface = newOne->getIfaceFromName(iter.key());
662 if (iface->getPurpose() == AbstractInterface::Clock) {
663 newOne->connectClock(iface->getName(), iter.value());
665 else if (iface->getPurpose() == AbstractInterface::Reset) {
666 newOne->connectReset(iface->getName(), iter.value());
670 params->blockToItem.insert(newOne,item);
672 params->unsaveModif = true;
678 void Dispatcher::addClkRstGenBlock(Context context, double frequency) {
679 static QString fctName = "Dispatcher::addClkRstGenBlock()";
681 cout << "call to " << qPrintable(fctName) << endl;
685 if (context == Design) {
687 params->clocks.append(frequency);
690 GroupBlock *group = params->getGraph()->getTopGroup();
691 GroupScene *scene = topGroupWidget->getScene();
693 // creating the clkrstgen block
694 ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
695 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true);
697 QString name = "clkrstgen_";
698 name += QString::number(params->clocks.size()-1);
699 newOne->setName(name);
701 // creating the box item
702 BoxItem* item = scene->createBoxItem(newOne, BoxItem::Left, AbstractBoxItem::Dimension);
703 item->setVisible(false);
705 ConnectedInterface* fromIfaceClk = NULL;
706 ConnectedInterface* fromIfaceReset = NULL;
707 QString clkName = "ext_clk_"+QString::number(params->clocks.size()-1);
708 QString rstName = "ext_reset_"+QString::number(params->clocks.size()-1);
709 fromIfaceClk = new GroupInterface(group,clkName, AbstractInterface::Input, AbstractInterface::Clock);
710 fromIfaceReset = new GroupInterface(group,rstName, AbstractInterface::Input, AbstractInterface::Reset);
711 group->addInterface(fromIfaceClk);
712 group->addInterface(fromIfaceReset);
713 // creating top group ext_clk iface item
714 GroupItem* groupItem = scene->getGroupItem();
715 InterfaceItem* fromIfaceItemClk = new InterfaceItem(0.5 , Parameters::West, fromIfaceClk, groupItem, params, true);
716 groupItem->addInterfaceItem(fromIfaceItemClk,true);
717 // creating top group ext_reset iface item
718 InterfaceItem* fromIfaceItemReset = new InterfaceItem(0.5 , Parameters::West, fromIfaceReset, groupItem, params, false);
719 groupItem->addInterfaceItem(fromIfaceItemReset,true);
720 // connecting ext_clk iface items
721 InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName("ext_clk");
722 if (toIfaceItemClk == NULL) {
723 cerr << "Abnormal case while connecting top group ext_clk to clkrstgen" << endl;
725 createConnection(context,fromIfaceItemClk, toIfaceItemClk, false);
726 // connecting ext_reset iface items
727 InterfaceItem* toIfaceItemReset = item->searchInterfaceItemByName("ext_reset");
728 if (toIfaceItemReset == NULL) {
729 cerr << "Abnormal case while connecting top group ext_reset to clkrstgen" << endl;
731 createConnection(context,fromIfaceItemReset, toIfaceItemReset, false);
733 params->blockToItem.insert(newOne,item);
734 params->unsaveModif = true;
740 GroupWidget *Dispatcher::createTopScene(Context context){
741 static QString fctName = "Dispatcher::createTopScene()";
743 cout << "call to " << qPrintable(fctName) << endl;
746 bool createIfaces = true;
747 if (context == Load) {
748 createIfaces = false;
750 // creating the graph and thus, the topgroup
751 Graph* graph = params->createGraph(createIfaces);
753 GroupBlock *topBlock = graph->getTopGroup();
754 // creating the top group widget
755 topGroupWidget = new GroupWidget(NULL,this,params);
756 currentGroupWidget = topGroupWidget;
757 // getting the newly created scene
758 GroupScene *scene = topGroupWidget->getScene();
759 scene->setId(sceneCounter++);
760 params->setTopScene(scene);
761 params->setCurrentScene(scene);
762 // creating the view part of the group
763 GroupItem *group = new GroupItem(NULL,topBlock,this,params);
764 // associate the top scene to the top group iten
765 scene->setGroupItem(group);
767 // adding the fake interface to the top group item
768 //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
769 //group->addInterface(item,true);
772 if (context == Design) {
774 double freq = params->clocks.at(0);
775 params->clocks.clear();
776 addClkRstGenBlock(context,freq);
779 groupList.append(topGroupWidget);
780 return topGroupWidget;
783 GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) {
784 static QString fctName = "Dispatcher::addNewEmptyGroup();";
786 cout << "call to " << qPrintable(fctName) << endl;
788 bool createIfaces = true;
789 if (context == Load) {
790 createIfaces = false;
793 // getting the parent block in the graph
794 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
795 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
796 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent, createIfaces);
797 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
798 // creating the BlockItem in the scene
799 BoxItem* newItem = scene->createBoxItem(groupBlock);
801 params->unsaveModif = true;
803 GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem);
804 if (show) child->show();
809 GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
810 static QString fctName = "Dispatcher::createChildScene()";
812 cout << "call to " << qPrintable(fctName) << endl;
815 GroupWidget* group = NULL;
816 /* NB: this method may be called during design process or when loading
817 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
818 cannot be initialized yet. This is why there are 2 cases below
821 if (upperItemOfGroupItem != NULL) {
822 // getting back the goup block already created
823 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
824 // creating the view part of the group
825 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
827 // creating the group widget
828 group = new GroupWidget(parentWidget, this, params);
829 // getting the newly created scene
830 GroupScene *scene = group->getScene();
831 scene->setId(sceneCounter++);
832 // affecting group item to the scene
833 scene->setGroupItem(groupItem);
834 groupList.append(group);
836 mainWindow->getLibrary()->updateComboScene();
839 GroupItem *groupItem = new GroupItem(this,params);
840 // creating the group widget
841 group = new GroupWidget(parentWidget, this, params);
842 // getting the newly created scene
843 GroupScene *scene = group->getScene();
844 // affecting group item to the scene
845 scene->setGroupItem(groupItem);
846 groupList.append(group);
851 void Dispatcher::destroyScene(Context context, GroupScene *scene) {
852 foreach(GroupScene* s, scene->getChildrenScene()) {
853 destroyScene(context, s);
856 if (scene->getNbChildScene() == 0) {
857 // remove scene from the parent list, if possible
858 if (scene->getParentScene() != NULL) {
859 scene->getParentScene()->removeChildScene(scene);
861 // destroy the GroupWidget
862 groupList.removeAll(scene->getGroupWidget());
863 scene->getGroupWidget()->deleteLater();
866 cerr << "Abnormal case when destroying a scene" << endl;
870 void Dispatcher::showRaiseWindow(Context context, BoxItem *item) {
871 static QString fctName = "Dispatcher::showRaiseWindow()";
873 cout << "call to " << qPrintable(fctName) << endl;
876 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
877 GroupItem* child = item->getChildGroupItem();
879 cerr << "abnormal case: child group item is null " << endl;
883 GroupWidget* win = child->getScene()->getGroupWidget();
887 win->activateWindow();
889 currentGroupWidget = win;
890 params->setCurrentScene(currentGroupWidget->getScene());
893 void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) {
894 static QString fctName = "Dispatcher::showRstClkIface()";
896 cout << "call to " << qPrintable(fctName) << endl;
899 item->setRstClkVisible(!item->isRstClkVisible());
903 void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) {
904 static QString fctName = "Dispatcher::showWishboneIface()";
906 cout << "call to " << qPrintable(fctName) << endl;
909 item->setWishboneVisible(!item->isWishboneVisible());
912 void Dispatcher::addNewFullGroup(Context context) {
913 static QString fctName = "Dispatcher::addNewFullGroup()";
915 cout << "call to " << qPrintable(fctName) << endl;
921 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
922 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
923 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
925 /* What must be done:
926 1 - creating a new GroupBlock
927 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
928 3 - creating a BlockItem that references the new GroupBlock
929 4 - creating a new GroupWidget
930 5 - creating a new GroupItem added to the scene of the GroupWidget
934 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
935 associated to the GroupItem of the current scene
937 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
938 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
939 /* step 2: moving selected blocks */
940 foreach(BlockItem* blockItem, listBlocks) {
941 parentBlock->removeBlock(blockItem->getRefBlock());
942 newGroupBlock->addBlock(blockItem->getRefBlock());
945 GroupItem *parent = currentGroup->getScene()->getGroupItem();
946 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
947 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
948 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
950 //create the new window
951 GroupWidget* win = new GroupWidget(this,params);
952 win->getScene()->setGroupItem(groupItem);
953 win->getScene()->addItem(groupItem);
954 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
955 params->addWindow(win);
959 params->getCurrentScene()->addBlockItem(blockItem);
960 params->getCurrentScene()->addItem(blockItem);
961 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
963 //replace selected blocks in the group
964 foreach(AbstractBoxItem *block, listBlocks){
965 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
966 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
967 params->getCurrentScene()->removeItem(block);
968 params->getCurrentScene()->removeBlockItem(block);
970 groupBlock->addBlock(block->getRefBlock());
971 listAbstractBlocks.append(block->getRefBlock());
973 block->setUpperItem(groupItem);
974 groupItem->addBlockItem(block);
975 win->getScene()->addItem(block);
976 win->getScene()->addBlockItem(block);
979 //replace connection between selected blocks in the group
980 foreach(ConnectionItem *conn, connections){
981 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
982 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
983 parent->removeConnection(conn);
984 params->getCurrentScene()->removeItem(conn);
986 groupItem->addConnection(conn);
987 win->getScene()->addItem(conn);
992 //create new interfaces and connections for the new group
993 foreach(AbstractBoxItem *block, listBlocks){
994 foreach(InterfaceItem *inter, block->getInterfaces()){
995 cout << "inter : " << inter->getName().toStdString() << endl;
996 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
997 cout << "connected from non null" << endl;
998 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
1000 AbstractInterface *iface = inter->refInter->clone(0);
1001 iface->setName(iface->getName()+"_group");
1002 groupBlock->addInterface(iface);
1004 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1005 blockItem->addInterface(ifaceItem);
1006 blockItem->resetInterfacesPosition();
1008 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
1009 groupItem->addInterface(ifaceGroupItem);
1010 groupItem->resetInterfacesPosition();
1011 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1012 if(conn->getToInterfaceItem() == inter){
1013 conn->setToInterfaceItem(ifaceItem);
1014 ifaceItem->refInter->setConnectedFrom(NULL);
1015 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
1016 connect(ifaceItem,conn->getFromInterfaceItem());
1019 params->setCurrentWindow(win);
1021 inter->refInter->setConnectedFrom(NULL);
1022 ifaceGroupItem->refInter->clearConnectedTo();
1023 connect(inter,ifaceGroupItem);
1024 params->setCurrentWindow(mainWindow);
1028 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
1029 cout << "connected to non null" << endl;
1030 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
1031 if(!listAbstractBlocks.contains(iface->getOwner())){
1033 AbstractInterface *iface = inter->refInter->clone(0);
1034 iface->setName(iface->getName()+"_group");
1035 groupBlock->addInterface(iface);
1037 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1038 blockItem->addInterface(ifaceItem);
1039 blockItem->resetInterfacesPosition();
1041 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1042 if(conn->getFromInterfaceItem() == inter){
1043 conn->setFromInterfaceItem(ifaceItem);
1044 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
1045 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
1049 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
1050 groupItem->addInterface(ifaceGroupItem);
1051 groupItem->resetInterfacesPosition();
1052 inter->refInter->clearConnectedTo();
1053 ifaceGroupItem->refInter->setConnectedFrom(NULL);
1054 connect(ifaceGroupItem,inter);
1063 parent->updateShape();
1064 currentGroup->getScene()->updateConnectionItemsShape();
1066 groupItem->updateShape();
1067 win->getScene()->updateConnectionItemsShape();
1068 groupItem->update(groupItem->boundingRect());
1073 void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
1074 static QString fctName = "Dispatcher::removeBoxItem()";
1075 #ifdef DEBUG_FCTNAME
1076 cout << "call to " << qPrintable(fctName) << endl;
1079 if (context != Design) return;
1081 /* a BoxItem (group of func) can be removed only if none of its
1082 interfaces is connected to a group interface that is itself
1083 connected to another one.
1085 bool canRemove = true;
1087 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1088 foreach(ConnectionItem* conn, ifaceItem->connections) {
1089 InterfaceItem* other = NULL;
1090 if (conn->getFromInterfaceItem() == ifaceItem) {
1091 other = conn->getToInterfaceItem();
1094 other = conn->getFromInterfaceItem();
1097 if (other->getOwner()->isGroupItem()) {
1098 ConnectedInterface* ref = other->refInter;
1099 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1106 QMessageBox::warning(NULL,"Forbidden operation",
1107 "The block has at least one connection to a group interface that is totally connected.",
1113 if (item->getRefBlock()->isFunctionalBlock()) {
1114 msg = "Removing block ";
1117 msg = "Removing group ";
1119 msg += item->getRefBlock()->getName();
1120 msg += " and all its connections.\n\nAre you sure ?";
1122 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1123 if (ret == QMessageBox::Cancel) {
1126 removeAllBlockConnections(context, item);
1128 if (item->getRefBlock()->isFunctionalBlock()) {
1129 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1130 item->getScene()->removeBoxItem(item);
1131 params->getGraph()->removeFunctionalBlock(block);
1132 params->blockToItem.remove(block);
1135 else if (item->getRefBlock()->isGroupBlock()) {
1137 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1139 // remove all child scenes recursively
1140 GroupItem* subgroup = item->getChildGroupItem();
1141 destroyScene(context, subgroup->getScene());
1142 // remove the BoxItem
1143 item->getScene()->removeBoxItem(item);
1144 // remove the group from the graph
1145 params->getGraph()->removeGroupBlock(group);
1149 void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) {
1150 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1151 #ifdef DEBUG_FCTNAME
1152 cout << "call to " << qPrintable(fctName) << endl;
1155 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1156 foreach(ConnectionItem* conn, ifaceItem->connections) {
1157 removeConnection(context, conn);
1162 void Dispatcher::removeSourceItem(Context context, SourceItem *item) {
1163 static QString fctName = "Dispatcher::removeSourceItem()";
1164 #ifdef DEBUG_FCTNAME
1165 cout << "call to " << qPrintable(fctName) << endl;
1168 QString msg = "Removing source ";
1170 msg += item->getRefBlock()->getName();
1171 msg += " and all its connections.\n\nAre you sure ?";
1173 int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1174 if (ret == QMessageBox::Cancel) {
1177 removeAllBlockConnections(context, item);
1179 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1180 item->getScene()->removeSourceItem(item);
1181 params->getGraph()->removeSourceBlock(block);
1185 void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
1186 static QString fctName = "Dispatcher::removeConnection()";
1187 #ifdef DEBUG_FCTNAME
1188 cout << "call to " << qPrintable(fctName) << endl;
1190 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1191 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1194 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1197 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1198 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1200 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1201 ConnectedInterface *toInter = toIfaceItem->refInter;
1203 // test if one of the interface bounded to item is owned by a GroupItem
1204 if (fromIfaceItem->getOwner()->isGroupItem()) {
1205 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1206 groupIfaceItem = fromIfaceItem;
1208 else if (toIfaceItem->getOwner()->isGroupItem()) {
1209 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1210 groupIfaceItem = toIfaceItem;
1213 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1216 // removing the connection from graph
1218 cout << "removing connections from graph ..." ;
1220 fromInter->disconnectTo(toInter);
1223 cout << "done." << endl ;
1226 // removing the connection from scene
1228 cout << "removing connections from scene ..." ;
1230 groupItem->getScene()->removeConnectionItem(connItem);
1233 cout << "done." << endl ;
1236 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1237 if (groupIfaceItem != NULL) {
1239 // determine if the interface must be removed since it has no more connections.
1240 bool groupInterRemove = false;
1241 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1243 if (groupInterRemove) {
1244 // get the GroupInterface from interface item
1245 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1246 // remove interface from GroupItem, and delete it.
1247 groupItem->removeInterfaceItem(groupIfaceItem);
1248 // get the parent BoxItem of GroupItem if it exists.
1249 BoxItem* parent2Item = groupItem->getParentItem();
1250 if (parent2Item != NULL) {
1251 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1252 // remove interface intem in parent BoxItem
1253 parent2Item->removeInterfaceItem(group2IfaceItem);
1255 // remove GroupInterface in the graph.
1256 groupInter->getOwner()->removeInterface(groupInter);
1261 void Dispatcher::showBlocksLibrary(){
1262 cout << "showing block library" << endl;
1263 mainWindow->getLibrary()->show();
1264 mainWindow->getLibrary()->raise();
1267 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
1268 QDialog* dial = new InterfacePropertiesDialog(inter);
1272 /* connectInterToGroup() :
1273 The only way for a block (functional of group) within a GroupItem to be connected
1274 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1275 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1278 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
1280 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1281 ConnectedInterface *refInter = item->refInter;
1282 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1283 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1284 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1285 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1287 // creating/adding the group interface in the graph model
1288 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1289 parentItem->getRefBlock()->addInterface(groupInter);
1290 // creating/adding the group control interface in the graph model if the purpose is data
1291 if (refInter->getPurpose() == AbstractInterface::Data) {
1292 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1293 groupCtlInter->setAssociatedIface(groupInter);
1294 parentItem->getRefBlock()->addInterface(groupCtlInter);
1296 // creating/adding the group interface in the current scene model, and connection item
1297 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1298 parentItem->addInterfaceItem(groupIfaceItem,true);
1300 // creating the connection, in graph and with an item
1301 createConnection(context, item, groupIfaceItem);
1303 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1304 BoxItem* parent2Item = parentItem->getParentItem();
1305 if(parent2Item != NULL){
1306 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1307 parent2Item->addInterfaceItem(blockIfaceItem,true);
1311 parentItem->getScene()->updateConnectionItemsShape();
1312 unselectAllItems(context);
1313 params->unsaveModif = true;
1316 void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) {
1317 static QString fctName = "Dispatcher::removeBlockInterface()";
1318 #ifdef DEBUG_FCTNAME
1319 cout << "call to " << qPrintable(fctName) << endl;
1322 /* first, remove all connections from item
1323 NB: if there is a connection to a group interface, then this
1324 method should not be called if the group interface is also
1325 connected to another interface. Normally, this is not possible
1326 because such a check is done when creating the contextual menu
1327 that allows to remove an interface.
1329 foreach(ConnectionItem* conn, item->connections) {
1330 removeConnection(context, conn);
1333 ConnectedInterface* ref = item->refInter;
1334 item->getOwner()->removeInterfaceItem(item);
1335 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1336 fun->removeInterface(ref);
1339 void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
1340 static QString fctName = "Dispatcher::removeGroupInterface()";
1341 #ifdef DEBUG_FCTNAME
1342 cout << "call to " << qPrintable(fctName) << endl;
1345 /* NB: just remove all connections from/to this item, since when there are no more
1346 ones to a GroupItem, it is automatically deleted.
1348 foreach(ConnectionItem* conn, item->connections) {
1349 removeConnection(context, conn);
1353 QMap<int, QString> Dispatcher::getAllGroupNames() {
1355 QMap<int, QString> list;
1356 foreach(GroupWidget *group, groupList) {
1357 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1362 GroupScene* Dispatcher::getSceneById(int id) {
1363 foreach(GroupWidget *group, groupList){
1364 if(group->getScene()->getId() == id)
1365 return group->getScene();
1367 cout << "search scene by id :" << id << " :: not found..." << endl;
1371 GroupItem *Dispatcher::getGroupItemById(int id) {
1372 foreach(GroupWidget *group, groupList) {
1373 GroupScene* scene = group->getScene();
1374 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1376 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1380 BoxItem *Dispatcher::getBoxItemById(int id) {
1381 foreach(GroupWidget *group, groupList) {
1383 GroupScene* scene = group->getScene();
1384 foreach(BoxItem *item, scene->getBoxItems()){
1385 if(item->getId() == id){
1390 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1394 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1396 foreach(GroupWidget *group, groupList) {
1398 GroupScene* scene = group->getScene();
1400 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1401 if(item->getId() == id){
1405 foreach(BoxItem *block, scene->getBoxItems()){
1406 foreach(InterfaceItem *item, block->getInterfaces()){
1407 if(item->getId() == id){
1413 cout << "search interface by id :" << id << " :: not found..." << endl;
1417 void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) {
1418 static QString fctName = "Dispatcher::findGraphModifications()";
1419 #ifdef DEBUG_FCTNAME
1420 cout << "call to " << qPrintable(fctName) << endl;
1423 block->computeAdmittanceDelays();
1424 // get the block item that is associated to block
1425 BoxItem* toBlockItem = params->blockToItem.value(block);
1427 /* VERSION 1: just add delays if needed */
1428 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1429 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1430 while (iterD.hasNext()) {
1432 QList<int>* delay = iterD.value();
1433 if (delay->at(0) > 0) {
1434 // create delay and associate it to the connected input
1436 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1437 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1438 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1439 toIface->setInputModifier(mod);
1441 toBlockItem->update();