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 "StimuliItem.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::renameStimuliItem(Context context, StimuliItem *item){
385 static QString fctName = "Dispatcher::renameStimuliItem()";
387 cout << "call to " << qPrintable(fctName) << endl;
390 GroupWidget* win = item->getScene()->getGroupWidget();
395 text = QInputDialog::getText(win, "Rename a stimuli",
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()->getStimuliBlockByName(text);
411 QMessageBox::warning(win,"Error in given name",
412 "the name provided is similar to that of another stimuli 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::duplicateStimuliItem(Context context, StimuliItem *item) {
568 static QString fctName = "Dispatcher::duplicateStimuliItem()";
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()->duplicateStimuliBlock(funBlock);
583 // adding to the view
584 scene->createStimuliItem(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 newStimuli = 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->isSourceBlock())) {
640 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 ?");
641 if (ret == QMessageBox::Yes) {
646 FunctionalBlock* newOne = params->getGraph()->createStimuliBlock(ref, true);
647 scene->createStimuliItem(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->getGraph()->addClock(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->getGraph()->getClocks().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->getGraph()->getClocks().size()-1);
708 QString rstName = "ext_reset_"+QString::number(params->getGraph()->getClocks().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, double mainClock){
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->initGraph(createIfaces);
752 graph->addClock(mainClock);
754 GroupBlock *topBlock = graph->getTopGroup();
755 // creating the top group widget
756 topGroupWidget = new GroupWidget(NULL,this,params);
757 currentGroupWidget = topGroupWidget;
758 // getting the newly created scene
759 GroupScene *scene = topGroupWidget->getScene();
760 scene->setId(sceneCounter++);
761 params->setTopScene(scene);
762 params->setCurrentScene(scene);
763 // creating the view part of the group
764 GroupItem *group = new GroupItem(NULL,topBlock,this,params);
765 // associate the top scene to the top group iten
766 scene->setGroupItem(group);
768 // adding the fake interface to the top group item
769 //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
770 //group->addInterface(item,true);
773 if (context == Design) {
775 double freq = params->getGraph()->getClock(0);
776 params->getGraph()->resetClocks();
777 addClkRstGenBlock(context,freq);
780 groupList.append(topGroupWidget);
781 return topGroupWidget;
784 GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) {
785 static QString fctName = "Dispatcher::addNewEmptyGroup();";
787 cout << "call to " << qPrintable(fctName) << endl;
789 bool createIfaces = true;
790 if (context == Load) {
791 createIfaces = false;
794 // getting the parent block in the graph
795 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
796 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
797 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent, createIfaces);
798 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
799 // creating the BlockItem in the scene
800 BoxItem* newItem = scene->createBoxItem(groupBlock);
802 params->unsaveModif = true;
804 GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem);
805 if (show) child->show();
810 GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
811 static QString fctName = "Dispatcher::createChildScene()";
813 cout << "call to " << qPrintable(fctName) << endl;
816 GroupWidget* group = NULL;
817 /* NB: this method may be called during design process or when loading
818 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
819 cannot be initialized yet. This is why there are 2 cases below
822 if (upperItemOfGroupItem != NULL) {
823 // getting back the goup block already created
824 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
825 // creating the view part of the group
826 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
828 // creating the group widget
829 group = new GroupWidget(parentWidget, this, params);
830 // getting the newly created scene
831 GroupScene *scene = group->getScene();
832 scene->setId(sceneCounter++);
833 // affecting group item to the scene
834 scene->setGroupItem(groupItem);
835 groupList.append(group);
837 mainWindow->getLibrary()->updateComboScene();
840 GroupItem *groupItem = new GroupItem(this,params);
841 // creating the group widget
842 group = new GroupWidget(parentWidget, this, params);
843 // getting the newly created scene
844 GroupScene *scene = group->getScene();
845 // affecting group item to the scene
846 scene->setGroupItem(groupItem);
847 groupList.append(group);
852 void Dispatcher::destroyScene(Context context, GroupScene *scene) {
853 foreach(GroupScene* s, scene->getChildrenScene()) {
854 destroyScene(context, s);
857 if (scene->getNbChildScene() == 0) {
858 // remove scene from the parent list, if possible
859 if (scene->getParentScene() != NULL) {
860 scene->getParentScene()->removeChildScene(scene);
862 // destroy the GroupWidget
863 groupList.removeAll(scene->getGroupWidget());
864 scene->getGroupWidget()->deleteLater();
867 cerr << "Abnormal case when destroying a scene" << endl;
871 void Dispatcher::showRaiseWindow(Context context, BoxItem *item) {
872 static QString fctName = "Dispatcher::showRaiseWindow()";
874 cout << "call to " << qPrintable(fctName) << endl;
877 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
878 GroupItem* child = item->getChildGroupItem();
880 cerr << "abnormal case: child group item is null " << endl;
884 GroupWidget* win = child->getScene()->getGroupWidget();
888 win->activateWindow();
890 currentGroupWidget = win;
891 params->setCurrentScene(currentGroupWidget->getScene());
894 void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) {
895 static QString fctName = "Dispatcher::showRstClkIface()";
897 cout << "call to " << qPrintable(fctName) << endl;
900 item->setRstClkVisible(!item->isRstClkVisible());
904 void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) {
905 static QString fctName = "Dispatcher::showWishboneIface()";
907 cout << "call to " << qPrintable(fctName) << endl;
910 item->setWishboneVisible(!item->isWishboneVisible());
913 void Dispatcher::addNewFullGroup(Context context) {
914 static QString fctName = "Dispatcher::addNewFullGroup()";
916 cout << "call to " << qPrintable(fctName) << endl;
922 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
923 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
924 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
926 /* What must be done:
927 1 - creating a new GroupBlock
928 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
929 3 - creating a BlockItem that references the new GroupBlock
930 4 - creating a new GroupWidget
931 5 - creating a new GroupItem added to the scene of the GroupWidget
935 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
936 associated to the GroupItem of the current scene
938 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
939 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
940 /* step 2: moving selected blocks */
941 foreach(BlockItem* blockItem, listBlocks) {
942 parentBlock->removeBlock(blockItem->getRefBlock());
943 newGroupBlock->addBlock(blockItem->getRefBlock());
946 GroupItem *parent = currentGroup->getScene()->getGroupItem();
947 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
948 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
949 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
951 //create the new window
952 GroupWidget* win = new GroupWidget(this,params);
953 win->getScene()->setGroupItem(groupItem);
954 win->getScene()->addItem(groupItem);
955 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
956 params->addWindow(win);
960 params->getCurrentScene()->addBlockItem(blockItem);
961 params->getCurrentScene()->addItem(blockItem);
962 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
964 //replace selected blocks in the group
965 foreach(AbstractBoxItem *block, listBlocks){
966 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
967 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
968 params->getCurrentScene()->removeItem(block);
969 params->getCurrentScene()->removeBlockItem(block);
971 groupBlock->addBlock(block->getRefBlock());
972 listAbstractBlocks.append(block->getRefBlock());
974 block->setUpperItem(groupItem);
975 groupItem->addBlockItem(block);
976 win->getScene()->addItem(block);
977 win->getScene()->addBlockItem(block);
980 //replace connection between selected blocks in the group
981 foreach(ConnectionItem *conn, connections){
982 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
983 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
984 parent->removeConnection(conn);
985 params->getCurrentScene()->removeItem(conn);
987 groupItem->addConnection(conn);
988 win->getScene()->addItem(conn);
993 //create new interfaces and connections for the new group
994 foreach(AbstractBoxItem *block, listBlocks){
995 foreach(InterfaceItem *inter, block->getInterfaces()){
996 cout << "inter : " << inter->getName().toStdString() << endl;
997 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
998 cout << "connected from non null" << endl;
999 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
1001 AbstractInterface *iface = inter->refInter->clone(0);
1002 iface->setName(iface->getName()+"_group");
1003 groupBlock->addInterface(iface);
1005 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1006 blockItem->addInterface(ifaceItem);
1007 blockItem->resetInterfacesPosition();
1009 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
1010 groupItem->addInterface(ifaceGroupItem);
1011 groupItem->resetInterfacesPosition();
1012 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1013 if(conn->getToInterfaceItem() == inter){
1014 conn->setToInterfaceItem(ifaceItem);
1015 ifaceItem->refInter->setConnectedFrom(NULL);
1016 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
1017 connect(ifaceItem,conn->getFromInterfaceItem());
1020 params->setCurrentWindow(win);
1022 inter->refInter->setConnectedFrom(NULL);
1023 ifaceGroupItem->refInter->clearConnectedTo();
1024 connect(inter,ifaceGroupItem);
1025 params->setCurrentWindow(mainWindow);
1029 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
1030 cout << "connected to non null" << endl;
1031 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
1032 if(!listAbstractBlocks.contains(iface->getOwner())){
1034 AbstractInterface *iface = inter->refInter->clone(0);
1035 iface->setName(iface->getName()+"_group");
1036 groupBlock->addInterface(iface);
1038 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
1039 blockItem->addInterface(ifaceItem);
1040 blockItem->resetInterfacesPosition();
1042 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
1043 if(conn->getFromInterfaceItem() == inter){
1044 conn->setFromInterfaceItem(ifaceItem);
1045 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
1046 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
1050 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
1051 groupItem->addInterface(ifaceGroupItem);
1052 groupItem->resetInterfacesPosition();
1053 inter->refInter->clearConnectedTo();
1054 ifaceGroupItem->refInter->setConnectedFrom(NULL);
1055 connect(ifaceGroupItem,inter);
1064 parent->updateShape();
1065 currentGroup->getScene()->updateConnectionItemsShape();
1067 groupItem->updateShape();
1068 win->getScene()->updateConnectionItemsShape();
1069 groupItem->update(groupItem->boundingRect());
1074 void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
1075 static QString fctName = "Dispatcher::removeBoxItem()";
1076 #ifdef DEBUG_FCTNAME
1077 cout << "call to " << qPrintable(fctName) << endl;
1080 if (context != Design) return;
1082 /* a BoxItem (group of func) can be removed only if none of its
1083 interfaces is connected to a group interface that is itself
1084 connected to another one.
1086 bool canRemove = true;
1088 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1089 foreach(ConnectionItem* conn, ifaceItem->connections) {
1090 InterfaceItem* other = NULL;
1091 if (conn->getFromInterfaceItem() == ifaceItem) {
1092 other = conn->getToInterfaceItem();
1095 other = conn->getFromInterfaceItem();
1098 if (other->getOwner()->isGroupItem()) {
1099 ConnectedInterface* ref = other->refInter;
1100 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1107 QMessageBox::warning(NULL,"Forbidden operation",
1108 "The block has at least one connection to a group interface that is totally connected.",
1114 if (item->getRefBlock()->isFunctionalBlock()) {
1115 msg = "Removing block ";
1118 msg = "Removing group ";
1120 msg += item->getRefBlock()->getName();
1121 msg += " and all its connections.\n\nAre you sure ?";
1123 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1124 if (ret == QMessageBox::Cancel) {
1127 removeAllBlockConnections(context, item);
1129 if (item->getRefBlock()->isFunctionalBlock()) {
1130 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1131 item->getScene()->removeBoxItem(item);
1132 params->getGraph()->removeFunctionalBlock(block);
1133 params->blockToItem.remove(block);
1136 else if (item->getRefBlock()->isGroupBlock()) {
1138 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1140 // remove all child scenes recursively
1141 GroupItem* subgroup = item->getChildGroupItem();
1142 destroyScene(context, subgroup->getScene());
1143 // remove the BoxItem
1144 item->getScene()->removeBoxItem(item);
1145 // remove the group from the graph
1146 params->getGraph()->removeGroupBlock(group);
1150 void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) {
1151 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1152 #ifdef DEBUG_FCTNAME
1153 cout << "call to " << qPrintable(fctName) << endl;
1156 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1157 foreach(ConnectionItem* conn, ifaceItem->connections) {
1158 removeConnection(context, conn);
1163 void Dispatcher::removeStimuliItem(Context context, StimuliItem *item) {
1164 static QString fctName = "Dispatcher::removeStimuliItem()";
1165 #ifdef DEBUG_FCTNAME
1166 cout << "call to " << qPrintable(fctName) << endl;
1169 QString msg = "Removing stimmuli ";
1171 msg += item->getRefBlock()->getName();
1172 msg += " and all its connections.\n\nAre you sure ?";
1174 int ret = QMessageBox::question(NULL,"Removing stimuli block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1175 if (ret == QMessageBox::Cancel) {
1178 removeAllBlockConnections(context, item);
1180 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1181 item->getScene()->removeStimuliItem(item);
1182 params->getGraph()->removeStimuliBlock(block);
1186 void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
1187 static QString fctName = "Dispatcher::removeConnection()";
1188 #ifdef DEBUG_FCTNAME
1189 cout << "call to " << qPrintable(fctName) << endl;
1191 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1192 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1195 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1198 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1199 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1201 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1202 ConnectedInterface *toInter = toIfaceItem->refInter;
1204 // test if one of the interface bounded to item is owned by a GroupItem
1205 if (fromIfaceItem->getOwner()->isGroupItem()) {
1206 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1207 groupIfaceItem = fromIfaceItem;
1209 else if (toIfaceItem->getOwner()->isGroupItem()) {
1210 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1211 groupIfaceItem = toIfaceItem;
1214 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1217 // removing the connection from graph
1219 cout << "removing connections from graph ..." ;
1221 fromInter->disconnectTo(toInter);
1224 cout << "done." << endl ;
1227 // removing the connection from scene
1229 cout << "removing connections from scene ..." ;
1231 groupItem->getScene()->removeConnectionItem(connItem);
1234 cout << "done." << endl ;
1237 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1238 if (groupIfaceItem != NULL) {
1240 // determine if the interface must be removed since it has no more connections.
1241 bool groupInterRemove = false;
1242 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1244 if (groupInterRemove) {
1245 // get the GroupInterface from interface item
1246 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1247 // remove interface from GroupItem, and delete it.
1248 groupItem->removeInterfaceItem(groupIfaceItem);
1249 // get the parent BoxItem of GroupItem if it exists.
1250 BoxItem* parent2Item = groupItem->getParentItem();
1251 if (parent2Item != NULL) {
1252 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1253 // remove interface intem in parent BoxItem
1254 parent2Item->removeInterfaceItem(group2IfaceItem);
1256 // remove GroupInterface in the graph.
1257 groupInter->getOwner()->removeInterface(groupInter);
1262 void Dispatcher::showBlocksLibrary(){
1263 cout << "showing block library" << endl;
1264 mainWindow->getLibrary()->show();
1265 mainWindow->getLibrary()->raise();
1268 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
1269 QDialog* dial = new InterfacePropertiesDialog(inter);
1273 /* connectInterToGroup() :
1274 The only way for a block (functional of group) within a GroupItem to be connected
1275 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1276 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1279 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
1281 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1282 ConnectedInterface *refInter = item->refInter;
1283 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1284 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1285 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1286 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1288 // creating/adding the group interface in the graph model
1289 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1290 parentItem->getRefBlock()->addInterface(groupInter);
1291 // creating/adding the group control interface in the graph model if the purpose is data
1292 if (refInter->getPurpose() == AbstractInterface::Data) {
1293 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1294 groupCtlInter->setAssociatedIface(groupInter);
1295 parentItem->getRefBlock()->addInterface(groupCtlInter);
1297 // creating/adding the group interface in the current scene model, and connection item
1298 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1299 parentItem->addInterfaceItem(groupIfaceItem,true);
1301 // creating the connection, in graph and with an item
1302 createConnection(context, item, groupIfaceItem);
1304 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1305 BoxItem* parent2Item = parentItem->getParentItem();
1306 if(parent2Item != NULL){
1307 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1308 parent2Item->addInterfaceItem(blockIfaceItem,true);
1312 parentItem->getScene()->updateConnectionItemsShape();
1313 unselectAllItems(context);
1314 params->unsaveModif = true;
1317 void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) {
1318 static QString fctName = "Dispatcher::removeBlockInterface()";
1319 #ifdef DEBUG_FCTNAME
1320 cout << "call to " << qPrintable(fctName) << endl;
1323 /* first, remove all connections from item
1324 NB: if there is a connection to a group interface, then this
1325 method should not be called if the group interface is also
1326 connected to another interface. Normally, this is not possible
1327 because such a check is done when creating the contextual menu
1328 that allows to remove an interface.
1330 foreach(ConnectionItem* conn, item->connections) {
1331 removeConnection(context, conn);
1334 ConnectedInterface* ref = item->refInter;
1335 item->getOwner()->removeInterfaceItem(item);
1336 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1337 fun->removeInterface(ref);
1340 void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
1341 static QString fctName = "Dispatcher::removeGroupInterface()";
1342 #ifdef DEBUG_FCTNAME
1343 cout << "call to " << qPrintable(fctName) << endl;
1346 /* NB: just remove all connections from/to this item, since when there are no more
1347 ones to a GroupItem, it is automatically deleted.
1349 foreach(ConnectionItem* conn, item->connections) {
1350 removeConnection(context, conn);
1354 QMap<int, QString> Dispatcher::getAllGroupNames() {
1356 QMap<int, QString> list;
1357 foreach(GroupWidget *group, groupList) {
1358 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1363 GroupScene* Dispatcher::getSceneById(int id) {
1364 foreach(GroupWidget *group, groupList){
1365 if(group->getScene()->getId() == id)
1366 return group->getScene();
1368 cout << "search scene by id :" << id << " :: not found..." << endl;
1372 GroupItem *Dispatcher::getGroupItemById(int id) {
1373 foreach(GroupWidget *group, groupList) {
1374 GroupScene* scene = group->getScene();
1375 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1377 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1381 BoxItem *Dispatcher::getBoxItemById(int id) {
1382 foreach(GroupWidget *group, groupList) {
1384 GroupScene* scene = group->getScene();
1385 foreach(BoxItem *item, scene->getBoxItems()){
1386 if(item->getId() == id){
1391 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1395 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1397 foreach(GroupWidget *group, groupList) {
1399 GroupScene* scene = group->getScene();
1401 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1402 if(item->getId() == id){
1406 foreach(BoxItem *block, scene->getBoxItems()){
1407 foreach(InterfaceItem *item, block->getInterfaces()){
1408 if(item->getId() == id){
1414 cout << "search interface by id :" << id << " :: not found..." << endl;
1418 void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) {
1419 static QString fctName = "Dispatcher::findGraphModifications()";
1420 #ifdef DEBUG_FCTNAME
1421 cout << "call to " << qPrintable(fctName) << endl;
1424 block->computeAdmittanceDelays();
1425 // get the block item that is associated to block
1426 BoxItem* toBlockItem = params->blockToItem.value(block);
1428 /* VERSION 1: just add delays if needed */
1429 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1430 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1431 while (iterD.hasNext()) {
1433 QList<int>* delay = iterD.value();
1434 if (delay->at(0) > 0) {
1435 // create delay and associate it to the connected input
1437 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1438 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1439 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1440 toIface->setInputModifier(mod);
1442 toBlockItem->update();