X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/f311fbc3e1436bf248c54225f0743cfa671c4bd7..HEAD:/Dispatcher.cpp diff --git a/Dispatcher.cpp b/Dispatcher.cpp index b191651..574243e 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -2,6 +2,8 @@ #include "Parameters.h" #include "MainWindow.h" +#include "ExternalResource.h" + #include "Graph.h" #include "ReferenceBlock.h" #include "GroupBlock.h" @@ -16,13 +18,20 @@ #include "GroupScene.h" #include "GroupItem.h" #include "BoxItem.h" +#include "StimuliItem.h" #include "InterfaceItem.h" #include "ConnectionItem.h" #include "BlockLibraryWidget.h" #include "BlockLibraryTree.h" -#include "InterfacePropertiesWindow.h" +#include "AbstractInputModifier.h" +#include "DelayInputModifier.h" + + +#include "InterfacePropertiesDialog.h" + +#include int Dispatcher::sceneCounter = 0; @@ -30,8 +39,8 @@ Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) { params = _params; mainWindow =_window; params->setDispatcher(this); - currentGroup = NULL; - topGroup = NULL; + currentGroupWidget = NULL; + topGroupWidget = NULL; } GroupWidget *Dispatcher::loadProject(const QString& filename) { @@ -44,6 +53,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { return NULL; } + /* // creating the top widget/scene topGroup = new GroupWidget(NULL,this,params); currentGroup = topGroup; @@ -52,9 +62,9 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { params->setTopScene(scene); params->setCurrentScene(scene); - +*/ try { - params->loadProject(root); + topGroupWidget = params->loadProject(root); } catch(Exception e){ cerr << qPrintable(e.getDefaultMessage()) << endl; @@ -63,8 +73,12 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { return NULL; } - groupList.append(topGroup); - return topGroup; + QFileInfo info(filename); + params->projectPath = info.absolutePath(); + params->projectName = info.baseName(); + cout << "project path = " << qPrintable(params->projectPath) << endl; + groupList.append(topGroupWidget); + return topGroupWidget; } void Dispatcher::closeCurrentProject() { @@ -72,64 +86,78 @@ void Dispatcher::closeCurrentProject() { foreach(GroupWidget* win, groupList) { win->deleteLater(); } + groupList.clear(); params->destroyGraph(); + topGroupWidget = NULL; + currentGroupWidget = NULL; + sceneCounter = 0; } -bool Dispatcher::connect(InterfaceItem *iface1, InterfaceItem *iface2) { +void Dispatcher::setSceneCounter(Context context, int value) { + + if (context != Load) return; + sceneCounter = value; +} + +bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) { + static QString fctName = "Dispatcher::createConnection()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + bool testClock = false; + if (context == Design) { + testClock = true; + } ConnectedInterface* ref1 = iface1->refInter; - ConnectedInterface* ref2 = iface2->refInter; + ConnectedInterface* ref2 = iface2->refInter; // connect both interface bool ok1 = false; bool ok2 = false; - if (ref1->canConnectTo(ref2)) { - ok1 = ref1->connectTo(ref2); - ok1 = ok1 & ref2->connectFrom(ref1); + cout << "trying to create a connection between " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); + cout << " and " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); + + // test the ref1->ref2 connection + if ((ref1->canConnectTo(ref2,testClock)) && (ref2->canConnectFrom(ref1,testClock))) { + ref1->connectTo(ref2); + ok1 = true; } - if (ref2->canConnectTo(ref1)) { - ok2 = ref2->connectTo(ref1); - ok2 = ok2 & ref1->connectFrom(ref2); + // if the first one did not work, test ref2->ref1 + if ((ok1 == false) && (ref2->canConnectTo(ref1,testClock)) && (ref1->canConnectFrom(ref2,testClock))) { + ref2->connectTo(ref1); + ok2 = true; } - if ((ok1 == true) || (ok2 == true)) { + if ((ok1 == true) || (ok2 == true)) { - iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2); + if (ok1) { + cout << " ... done with " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); + cout << " to " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); + iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible); + } + else { + cout << "... done with " << qPrintable(ref2->getOwner()->getName()) << "/" << qPrintable(ref2->getName()); + cout << " to " << qPrintable(ref1->getOwner()->getName()) << "/" << qPrintable(ref1->getName()); + iface2->getOwner()->getScene()->createConnectionItem(iface2,iface1, visible); + } - unselectAllItems(); - params->unsaveModif = true; + cout << endl; + + unselectAllItems(context); + params->unsaveModif = true; return true; } return false; } -void Dispatcher::checkSelection(){ - InterfaceItem *iface1 = NULL; - InterfaceItem *iface2 = NULL; - GroupScene *scene = params->getCurrentScene(); - QList list = scene->getGroupAndBlocks(); - foreach(AbstractBoxItem *block, list){ - InterfaceItem *tmp = block->getCurrentInterface(); - if (tmp != NULL) { - if (iface1 == NULL) { - iface1 = tmp; - } - else { - iface2 = tmp; - } - } - } - if(iface1 != NULL && iface2 != NULL){ - connect(iface1,iface2); - } -} - -void Dispatcher::unselectAllItems(int direction){ +void Dispatcher::unselectAllItems(Context context, int direction){ GroupScene *scene = params->getCurrentScene(); - foreach(BoxItem* block, scene->getBlockItems()) { + foreach(BoxItem* block, scene->getBoxItems()) { block->setSelected(false); block->setCurrentInterface(NULL); } @@ -137,14 +165,14 @@ void Dispatcher::unselectAllItems(int direction){ scene->update(); } -void Dispatcher::setCurrentGroupWidget(GroupWidget *win){ +void Dispatcher::setCurrentGroupWidget(Context context, GroupWidget *win){ win->setFocus(); win->changeConnectionMode(-1); - currentGroup = win; + currentGroupWidget = win; params->setCurrentScene(win->getScene()); } -void Dispatcher::changeConnectionMode(int mode){ +void Dispatcher::changeConnectionMode(Context context, int mode){ /* foreach(GroupWidget* win, groupList){ @@ -179,77 +207,465 @@ void Dispatcher::changeConnectionMode(int mode){ */ } -void Dispatcher::renameBlockOrGroup(AbstractBoxItem *item){ - static QString fctName = "Dispatcher::renameBlockOrGroup()"; +void Dispatcher::generateVHDL(Context context) throw(Exception) { + static QString fctName = "Dispatcher::generateVHDL()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } - bool ok; - QString text = QInputDialog::getText(NULL, "Rename an block/group", - "New name:", QLineEdit::Normal, - item->getRefBlock()->getName(), &ok); - if(ok){ - if(!text.isEmpty() && text.length() < 30){ - item->getRefBlock()->setName(text); - if(item->isGroupItem()){ - if (currentGroup->isTopGroup()) { - mainWindow->setWindowTitle("blast - "+text); - } - else { - currentGroup->setWindowTitle("blast - "+text); - } + QDir baseDir(params->projectPath); + QDir srcDir(params->projectPath+"/src"); + + if (!baseDir.exists()) { + cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl; + return; + } + + if (srcDir.exists()) { + srcDir.removeRecursively(); + } + baseDir.mkdir("src"); + + if (! baseDir.exists("testbench")) { + baseDir.mkdir("testbench"); + } + if (! baseDir.exists("Makefile")) { + QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim"); + QString dest = params->projectPath; + dest += "/Makefile"; + make.copy(dest); + } + + // generate VHDL + copying external resources + QString dest = params->projectPath; + dest += "/src/"; + try { + params->getGraph()->generateVHDL(dest); + + QList extResources = params->getGraph()->getExternalResources(); + foreach(QString name, extResources) { + cout << qPrintable(name) << endl; + QList lstRes = params->searchResourceByName(name); + foreach(ExternalResource* res, lstRes) { + QFile resFile(res->getFile()); + QFileInfo info(res->getFile()); + QString destFile = dest+info.fileName(); + cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl; + resFile.copy(destFile); } + } + } + catch(Exception e) { + throw(e); + } + // generate testbench + dest = params->projectPath; + dest += "/testbench/"; + dest += params->projectName; + dest += "_tb.vhd"; + try { + params->getGraph()->generateTestbench(params->projectName, dest); + } + catch(Exception e) { + throw(e); + } - mainWindow->getLibrary()->updateComboScene(); + // creating parameters file + QString paramName = params->projectPath+"/params-isim.txt"; + QFile paramFile(paramName); + if (!paramFile.open(QIODevice::WriteOnly)) { + throw(Exception(PROJECTPATH_NOACCESS)); + } + QTextStream out(¶mFile); + out << "PROJECT_NAME := " << params->projectName << endl << endl; + out << "SRC_DIR := src" << endl; + out << "TB_DIR := testbench" << endl << endl; + out << "VHDL_SRC := "; + QStringList filter; + filter << "*.vhd" ; + srcDir.setNameFilters(filter); + QStringList listVHDL = srcDir.entryList(); + for(int j=0;j 0) { + out << "\t"; + } + out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j)); + if (j != listVHDL.size()-1) { + out << " \\"; + } + out << endl; + } + out << endl; + out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl; + out << "TB_SRC := $(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl; + out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl; + + paramFile.close(); + + QString msg = "VHDL generation completed successfully. Go to "; + msg += params->projectPath+" and type the following commands to launch a simulation:\n"; + msg += "\tmake clean\n"; + msg += "\tmake\n"; + msg += "\tmake view\n"; + QMessageBox::information(mainWindow,"VHDL generation", msg, QMessageBox::Ok); + +} + +void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){ + static QString fctName = "Dispatcher::generateBlockVHDL()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + if (item->getRefBlock()->isFunctionalBlock()) { + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + try { + block->generateVHDL(params->projectPath); + } + catch(Exception e) { + cout << qPrintable(e.getMessage()) << endl; + } + } +} + +void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){ + static QString fctName = "Dispatcher::renameFunctionalBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a functional block", + "New name:", QLineEdit::Normal, + item->getRefBlock()->getName(), &ok); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; } else { - QMessageBox::warning(NULL,"Error in given name", - "the element name must be shorter than 30 characters and can't be empty!", + FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent())); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another functional block within the group", + QMessageBox::Ok); + ok = false; + } + } + } + + item->getRefBlock()->setName(text); + item->nameChanged(); +} + +void Dispatcher::renameGroupBlock(Context context, GroupItem *item){ + static QString fctName = "Dispatcher::renameGroupBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a group", + "New name:", QLineEdit::Normal, + item->getRefBlock()->getName(), &ok); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", QMessageBox::Ok); - renameBlockOrGroup(item); + ok = false; } + else { + GroupBlock* block = params->getGraph()->getGroupBlockByName(text); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another group", + QMessageBox::Ok); + ok = false; + } + } } + + item->getRefBlock()->setName(text); + if(item->getScene()->getGroupWidget()->isTopGroup()) { + mainWindow->setWindowTitle("blast - "+text); + } + else { + item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text); + } + item->nameChanged(); + mainWindow->getLibrary()->updateComboScene(); } -void Dispatcher::renameInterface(InterfaceItem *item) { +void Dispatcher::renameStimuliItem(Context context, StimuliItem *item){ + static QString fctName = "Dispatcher::renameStimuliItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a stimuli", + "New name:", QLineEdit::Normal, + item->getRefBlock()->getName(), &ok); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; + } + else { + FunctionalBlock* block = params->getGraph()->getStimuliBlockByName(text); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another stimuli block within the top group", + QMessageBox::Ok); + ok = false; + } + } + } + + item->getRefBlock()->setName(text); + item->nameChanged(); +} + + +void Dispatcher::renameInterface(Context context, InterfaceItem *item) { static QString fctName = "Dispatcher::renameInterface()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } - bool ok; - QString text = QInputDialog::getText(NULL, "Rename an interface", + GroupWidget* win = item->getOwner()->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename an interface", "New name:", QLineEdit::Normal, item->refInter->getName(), &ok); + + if (!ok) return; + + if (text == item->refInter->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the interface name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; + } + else { + AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text); + if (iface != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another interface", + QMessageBox::Ok); + ok = false; + } + } + } + item->refInter->setName(text); + AbstractInterface* assoIface = item->refInter->getAssociatedIface(); + if (assoIface != NULL) { + assoIface->setName(text+"_enb"); + } + item->updateName(text); + item->getOwner()->nameChanged(); +} - /* CAUTION: when renaming an interface item, there are two cases : - - it refers to a functional block interface (fbi): the fbi keeps its name - and the new name is given to item - - it refers to a group block interface (gbi) : both gbi and item store the new name +void Dispatcher::showPatterns(Context context, InterfaceItem *item) { + static QString fctName = "Dispatcher::showPatterns()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } - */ - if(ok && !text.isEmpty() && text.length() < 30) { - if (item->refInter->getOwner()->isGroupBlock()) { - item->refInter->setName(text); + QString msg = ""; + if (item->refInter->getDirection() == AbstractInterface::Input) { + msg = "Input pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is:\n"; + // get the precursor output pattern + ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface()); + QList* out = connIface->getConnectedFrom()->getOutputPattern(); + // get the modifier + AbstractInputModifier* modifier = connIface->getInputModifier(); + // check if the input is modified + if (modifier != NULL) { + + out = modifier->getModifiedInput(out); } - item->setName(text); + foreach(char c, *out) { + msg += QString::number((int)c); + } + msg += "\n"; } - else { - QMessageBox::warning(NULL,"Error in given name", - "the interface name must be shorter than 30 characters and can't be empty!", - QMessageBox::Ok); - renameInterface(item); + else if (item->refInter->getDirection() == AbstractInterface::Output) { + msg = "Output pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is:\n"; + ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface()); + if (iface->getOutputPattern() == NULL) return; + foreach(char c, *(iface->getOutputPattern())) { + msg += QString::number((int)c); + } + msg += "\n"; + } + QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok); +} + +void Dispatcher::showModifier(Context context, InterfaceItem *item) { + static QString fctName = "Dispatcher::showModifier()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + QString msg = ""; + ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface()); + AbstractInputModifier* mod = assoIface->getInputModifier(); + if (mod->isDelay()) { + DelayInputModifier* delay = (DelayInputModifier *)mod; + msg = "Pattern of iface "; + msg += item->refInter->getName(); + msg += " owned by "; + msg += item->refInter->getOwner()->getName(); + msg += " is modified by a simple delay of "; + msg += QString::number(delay->getDelayLength()); + + } + QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok); +} + +void Dispatcher::removeModifier(Context context, InterfaceItem *item) { + static QString fctName = "Dispatcher::removeModifier()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface()); + assoIface->clearInputModifier(); +} + + +void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){ + static QString fctName = "Dispatcher::duplicateBoxItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + + + GroupScene *scene = item->getScene(); + AbstractBlock* block = item->getRefBlock(); + AbstractBlock *newBlock; + + // only duplicate functional blocks + if(block->isFunctionalBlock()) { + + // adding to the model + FunctionalBlock* funBlock = (FunctionalBlock*)block; + newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock); + // adding to the view + scene->createBoxItem(newBlock); + + params->unsaveModif = true; } } -void Dispatcher::duplicateBlock(BoxItem *item){ - static QString fctName = "Dispatcher::duplicateBlock()"; +void Dispatcher::duplicateStimuliItem(Context context, StimuliItem *item) { + static QString fctName = "Dispatcher::duplicateStimuliItem()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + GroupScene *scene = item->getScene(); AbstractBlock* block = item->getRefBlock(); @@ -260,19 +676,25 @@ void Dispatcher::duplicateBlock(BoxItem *item){ // adding to the model FunctionalBlock* funBlock = (FunctionalBlock*)block; - newBlock = params->duplicateFunctionalBlock(funBlock); + newBlock = params->getGraph()->duplicateStimuliBlock(funBlock); // adding to the view - scene->createBlockItem(newBlock); + scene->createStimuliItem(newBlock); params->unsaveModif = true; } } -void Dispatcher::duplicateInterface(InterfaceItem *item) { - static QString fctName = "Dispatcher::duplicateInterface()"; +void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) { + static QString fctName = "Dispatcher::duplicateInterfaceItem()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } + AbstractInterface *refI = item->refInter; if (! refI->isFunctionalInterface()) return; @@ -281,124 +703,275 @@ void Dispatcher::duplicateInterface(InterfaceItem *item) { if(! refB->isFunctionalBlock()) return; FunctionalInterface* iface = (FunctionalInterface*)refI; - AbstractInterface *otherRef = iface->clone(); - if (otherRef == NULL) { + AbstractInterface *cloneIface = iface->clone(); + if (cloneIface == NULL) { QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok); return; } - refB->addInterface(otherRef); - - InterfaceItem *otherIface = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)otherRef,item->getOwner(),params); - item->getOwner()->addInterface(otherIface,true); + refB->addInterface(cloneIface); + + InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params); + item->getOwner()->addInterfaceItem(cloneIfaceItem,true); + + // creating control interface if needed + if (refI->getAssociatedIface() != NULL) { + QString ctlName = cloneIface->getName()+"_enb"; + ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1); + refB->addInterface(ctlIface); + if (! ctlIface->setAssociatedIface(cloneIface)) { + cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl; + } + } } -void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { +void Dispatcher::addBlock(Context context, int idCategory, int idBlock, int idScene, QHash clkRstToGen) { static QString fctName = "Dispatcher::addBlock()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + bool newStimuli = false; + + /* For now, this method is only used while designing and not loading */ + if (context == Design) { + GroupScene *scene = getSceneById(idScene); + ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock); + // if block has no inputs, propose to add it as a source to top scene + if ((scene->isTopScene()) && (ref->isSourceBlock())) { + 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 ?"); + if (ret == QMessageBox::Yes) { + newStimuli = true; + } + } + if (newStimuli) { + FunctionalBlock* newOne = params->getGraph()->createStimuliBlock(ref, true); + StimuliItem* item = scene->createStimuliItem(newOne); + QHashIterator iter(clkRstToGen); + while (iter.hasNext()) { + iter.next(); + AbstractInterface* iface = newOne->getIfaceFromName(iter.key()); + if (iface->getPurpose() == AbstractInterface::Clock) { + connectStimuliItemClock(context,item,iface->getName(),iter.value()); + } + else if (iface->getPurpose() == AbstractInterface::Reset) { + connectStimuliItemReset(context,item,iface->getName(),iter.value()); + } + } + } + else { + + GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); + FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true); + + // creating the box item + BoxItem* item = scene->createBoxItem(newOne); + + QHashIterator iter(clkRstToGen); + while (iter.hasNext()) { + iter.next(); + AbstractInterface* iface = newOne->getIfaceFromName(iter.key()); + if (iface->getPurpose() == AbstractInterface::Clock) { + connectBoxItemClock(context,item,iface->getName(),iter.value()); + } + else if (iface->getPurpose() == AbstractInterface::Reset) { + connectBoxItemReset(context,item,iface->getName(),iter.value()); + } + } + + params->blockToItem.insert(newOne,item); + } + params->unsaveModif = true; + } +} + +void Dispatcher::addClkRstGenBlock(Context context, double frequency) { + static QString fctName = "Dispatcher::addClkRstGenBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - GroupScene *scene = searchSceneById(idScene); - ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock); - GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); - FunctionalBlock* newOne = params->getGraph()->addFunctionalBlock(group, ref); - scene->createBlockItem(newOne); - params->unsaveModif = true; + + if (context == Design) { + + params->getGraph()->addClock(frequency); + + // get the top group + GroupBlock *group = params->getGraph()->getTopGroup(); + GroupScene *scene = topGroupWidget->getScene(); + + // creating the clkrstgen block + ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen"); + FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true); + + QString name = "clkrstgen_"; + name += QString::number(params->getGraph()->getClocks().size()-1); + newOne->setName(name); + + // creating the box item + BoxItem* item = scene->createBoxItem(newOne, BoxItem::Left, AbstractBoxItem::Dimension); + item->setVisible(false); + + ConnectedInterface* fromIfaceClk = NULL; + ConnectedInterface* fromIfaceReset = NULL; + QString clkName = "ext_clk_"+QString::number(params->getGraph()->getClocks().size()-1); + QString rstName = "ext_reset_"+QString::number(params->getGraph()->getClocks().size()-1); + fromIfaceClk = new GroupInterface(group,clkName, AbstractInterface::Input, AbstractInterface::Clock); + fromIfaceReset = new GroupInterface(group,rstName, AbstractInterface::Input, AbstractInterface::Reset); + group->addInterface(fromIfaceClk); + group->addInterface(fromIfaceReset); + // creating top group ext_clk iface item + GroupItem* groupItem = scene->getGroupItem(); + InterfaceItem* fromIfaceItemClk = new InterfaceItem(0.5 , Parameters::West, fromIfaceClk, groupItem, params, true); + groupItem->addInterfaceItem(fromIfaceItemClk,true); + // creating top group ext_reset iface item + InterfaceItem* fromIfaceItemReset = new InterfaceItem(0.5 , Parameters::West, fromIfaceReset, groupItem, params, false); + groupItem->addInterfaceItem(fromIfaceItemReset,true); + // connecting ext_clk iface items + InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName("ext_clk"); + if (toIfaceItemClk == NULL) { + cerr << "Abnormal case while connecting top group ext_clk to clkrstgen" << endl; + } + createConnection(context,fromIfaceItemClk, toIfaceItemClk, false); + // connecting ext_reset iface items + InterfaceItem* toIfaceItemReset = item->searchInterfaceItemByName("ext_reset"); + if (toIfaceItemReset == NULL) { + cerr << "Abnormal case while connecting top group ext_reset to clkrstgen" << endl; + } + createConnection(context,fromIfaceItemReset, toIfaceItemReset, false); + + params->blockToItem.insert(newOne,item); + params->unsaveModif = true; + } } -GroupWidget *Dispatcher::createTopScene(){ + +GroupWidget *Dispatcher::createTopScene(Context context, double mainClock){ static QString fctName = "Dispatcher::createTopScene()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - // creating the model part of the group - Graph* graph = params->createGraph(); - GroupBlock *refBlock = graph->getTopGroup(); - - // creating a fake and not connected interface - //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top); + Graph* graph = NULL; + // creating the graph and thus, the topgroup + if (context == Design) { + graph = params->initGraph(true); + graph->addClock(mainClock); + } + else if (context == Load) { + graph = params->initGraph(false); + } - // creating the group widget - topGroup = new GroupWidget(NULL,this,params); - currentGroup = topGroup; + // get the top group + GroupBlock *topBlock = graph->getTopGroup(); + // creating the top group widget + topGroupWidget = new GroupWidget(NULL,this,params); + currentGroupWidget = topGroupWidget; // getting the newly created scene - GroupScene *scene = topGroup->getScene(); + GroupScene *scene = topGroupWidget->getScene(); scene->setId(sceneCounter++); params->setTopScene(scene); params->setCurrentScene(scene); // creating the view part of the group - GroupItem *group = new GroupItem(NULL,refBlock,this,params); + GroupItem *group = new GroupItem(NULL,topBlock,this,params); + // associate the top scene to the top group iten + scene->setGroupItem(group); // adding the fake interface to the top group item //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params); //group->addInterface(item,true); - scene->setGroupItem(group); - groupList.append(topGroup); - return topGroup; + if (context == Design) { + // create clkrstgen + double freq = params->getGraph()->getClock(0); + params->getGraph()->resetClocks(); + addClkRstGenBlock(context,freq); + } + + groupList.append(topGroupWidget); + return topGroupWidget; } -void Dispatcher::addNewEmptyGroup(GroupScene* scene) { +GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) { static QString fctName = "Dispatcher::addNewEmptyGroup();"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + bool createIfaces = true; + if (context == Load) { + createIfaces = false; + } // getting the parent block in the graph GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); cout << "new group : parent = "<< qPrintable(parent->getName()) << endl; - GroupBlock* groupBlock = params->getGraph()->createChildBlock(parent); + GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent, createIfaces); cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl; // creating the BlockItem in the scene - BoxItem* newItem = scene->createBlockItem(groupBlock); + BoxItem* newItem = scene->createBoxItem(groupBlock); params->unsaveModif = true; - GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem); - child->show(); + GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem); + if (show) child->show(); + return child; } -GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) { +GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) { static QString fctName = "Dispatcher::createChildScene()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - // getting back the goup block already created - GroupBlock* groupBlock = NULL; - if (upperItemOfGroupItem != NULL) { - groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock()); - } - // creating the view part of the group - GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params); - // creating the group widget - GroupWidget* group = new GroupWidget(parentWidget, this, params); - // getting the newly created scene - GroupScene *scene = group->getScene(); - scene->setId(sceneCounter++); - // affecting group item to the scene - scene->setGroupItem(groupItem); - groupList.append(group); - - mainWindow->getLibrary()->updateComboScene(); + GroupWidget* group = NULL; + /* NB: this method may be called during design process or when loading + a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things + cannot be initialized yet. This is why there are 2 cases below + */ + if (upperItemOfGroupItem != NULL) { + // getting back the goup block already created + GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock()); + // creating the view part of the group + GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params); + + // creating the group widget + group = new GroupWidget(parentWidget, this, params); + // getting the newly created scene + GroupScene *scene = group->getScene(); + scene->setId(sceneCounter++); + // affecting group item to the scene + scene->setGroupItem(groupItem); + groupList.append(group); + + mainWindow->getLibrary()->updateComboScene(); + } + else { + GroupItem *groupItem = new GroupItem(this,params); + // creating the group widget + group = new GroupWidget(parentWidget, this, params); + // getting the newly created scene + GroupScene *scene = group->getScene(); + // affecting group item to the scene + scene->setGroupItem(groupItem); + groupList.append(group); + } return group; } -void Dispatcher::destroyScene(GroupScene *scene) { +void Dispatcher::destroyScene(Context context, GroupScene *scene) { foreach(GroupScene* s, scene->getChildrenScene()) { - destroyScene(s); + destroyScene(context, s); } if (scene->getNbChildScene() == 0) { - // remove scene from the parent list - scene->getParentScene()->removeChildScene(scene); + // remove scene from the parent list, if possible + if (scene->getParentScene() != NULL) { + scene->getParentScene()->removeChildScene(scene); + } // destroy the GroupWidget groupList.removeAll(scene->getGroupWidget()); scene->getGroupWidget()->deleteLater(); @@ -408,7 +981,7 @@ void Dispatcher::destroyScene(GroupScene *scene) { } } -void Dispatcher::showRaiseWindow(BoxItem *item) { +void Dispatcher::showRaiseWindow(Context context, BoxItem *item) { static QString fctName = "Dispatcher::showRaiseWindow()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; @@ -427,23 +1000,30 @@ void Dispatcher::showRaiseWindow(BoxItem *item) { win->raise(); win->activateWindow(); - currentGroup = win; - params->setCurrentScene(currentGroup->getScene()); + currentGroupWidget = win; + params->setCurrentScene(currentGroupWidget->getScene()); } -void Dispatcher::showRstClkInter(AbstractBoxItem *item) { - static QString fctName = "Dispatcher::showRstClkInter()"; +void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) { + static QString fctName = "Dispatcher::showRstClkIface()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif item->setRstClkVisible(!item->isRstClkVisible()); - item->resetInterfacesPosition(); + +} - item->getScene()->updateConnectionItemsShape(); +void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) { + static QString fctName = "Dispatcher::showWishboneIface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + item->setWishboneVisible(!item->isWishboneVisible()); } -void Dispatcher::addNewFullGroup() { +void Dispatcher::addNewFullGroup(Context context) { static QString fctName = "Dispatcher::addNewFullGroup()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; @@ -604,11 +1184,16 @@ void Dispatcher::addNewFullGroup() { #endif } -void Dispatcher::removeBlock(BoxItem *item) { - static QString fctName = "Dispatcher::removeBlock()"; +void Dispatcher::removeBoxItem(Context context, BoxItem *item) { + static QString fctName = "Dispatcher::removeBoxItem()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " << qPrintable(fctName) << " not in Design context" << endl; + return; + } /* a BoxItem (group of func) can be removed only if none of its interfaces is connected to a group interface that is itself @@ -655,13 +1240,14 @@ void Dispatcher::removeBlock(BoxItem *item) { if (ret == QMessageBox::Cancel) { return; } - removeAllBlockConnections(item); + removeAllBlockConnections(context, item); if (item->getRefBlock()->isFunctionalBlock()) { - FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); - GroupBlock* group = AB_TO_GRP(block->getParent()); - item->getScene()->removeBlockItem(item); - params->getGraph()->removeFunctionalBlock(block,group); + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + item->getScene()->removeBoxItem(item); + params->getGraph()->removeFunctionalBlock(block); + params->blockToItem.remove(block); + } else if (item->getRefBlock()->isGroupBlock()) { @@ -669,49 +1255,92 @@ void Dispatcher::removeBlock(BoxItem *item) { // remove all child scenes recursively GroupItem* subgroup = item->getChildGroupItem(); - destroyScene(subgroup->getScene()); + destroyScene(context, subgroup->getScene()); // remove the BoxItem - item->getScene()->removeBlockItem(item); + item->getScene()->removeBoxItem(item); // remove the group from the graph params->getGraph()->removeGroupBlock(group); } } -void Dispatcher::removeAllBlockConnections(BoxItem *item) { +void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) { static QString fctName = "Dispatcher::removeAllBlockConnection()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getInterfaces()) { foreach(ConnectionItem* conn, ifaceItem->connections) { - removeConnection(conn); + removeConnection(context, conn); } } } -void Dispatcher::removeConnection(ConnectionItem *conn) { +void Dispatcher::removeStimuliItem(Context context, StimuliItem *item) { + static QString fctName = "Dispatcher::removeStimuliItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getRefBlock()->getName(); + msg += " and all its connections.\n\nAre you sure ?"; + + int ret = QMessageBox::question(NULL,"Removing stimuli block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + if (ret == QMessageBox::Cancel) { + return; + } + removeAllBlockConnections(context, item); + + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + item->getScene()->removeStimuliItem(item); + params->getGraph()->removeStimuliBlock(block); +} + + +void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) { static QString fctName = "Dispatcher::removeConnection()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - InterfaceItem* fromIfaceItem = conn->getFromInterfaceItem(); - InterfaceItem* toIfaceItem = conn->getToInterfaceItem(); + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getFromInterfaceItem(); + InterfaceItem* toIfaceItem = connItem->getToInterfaceItem(); #ifdef DEBUG cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl; #endif - InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem - GroupItem* groupItem = NULL; + InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not + GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem + ConnectedInterface *fromInter = fromIfaceItem->refInter; + ConnectedInterface *toInter = toIfaceItem->refInter; + + // test if one of the interface bounded to item is owned by a GroupItem if (fromIfaceItem->getOwner()->isGroupItem()) { - groupIfaceItem = fromIfaceItem; - groupItem = toIfaceItem->getOwner()->getScene()->getGroupItem(); + groupItem = ABI_TO_GI(fromIfaceItem->getOwner()); + groupIfaceItem = fromIfaceItem; } else if (toIfaceItem->getOwner()->isGroupItem()) { - groupIfaceItem = toIfaceItem; - groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem(); + groupItem = ABI_TO_GI(toIfaceItem->getOwner()); + groupIfaceItem = toIfaceItem; } else { groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem(); @@ -720,19 +1349,9 @@ void Dispatcher::removeConnection(ConnectionItem *conn) { // removing the connection from graph #ifdef DEBUG cout << "removing connections from graph ..." ; -#endif - ConnectedInterface *fromInter = fromIfaceItem->refInter; - ConnectedInterface *toInter = toIfaceItem->refInter; - if (fromInter->getDirection() == AbstractInterface::InOut) { - fromInter->clearConnectedTo(); - fromInter->clearConnectedFrom(); - toInter->clearConnectedTo(); - toInter->clearConnectedFrom(); - } - else { - fromInter->removeConnectedTo(toInter); - toInter->clearConnectedFrom(); - } +#endif + fromInter->disconnectTo(toInter); + #ifdef DEBUG cout << "done." << endl ; #endif @@ -740,202 +1359,287 @@ void Dispatcher::removeConnection(ConnectionItem *conn) { // removing the connection from scene #ifdef DEBUG cout << "removing connections from scene ..." ; -#endif - fromIfaceItem->removeConnectionItem(conn); - toIfaceItem->removeConnectionItem(conn); - groupItem->getScene()->removeConnectionItem(conn); +#endif + groupItem->getScene()->removeConnectionItem(connItem); #ifdef DEBUG cout << "done." << endl ; #endif - + + // if one of the interface bounded to connItem is owned by the GroupItem of the scene if (groupIfaceItem != NULL) { - ConnectedInterface* groupInter = groupIfaceItem->refInter; - groupItem->removeInterface(groupIfaceItem); - - BoxItem* parent2Item = groupItem->getParentItem(); - if (parent2Item != NULL) { - InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter); - parent2Item->removeInterface(group2IfaceItem); + + // determine if the interface must be removed since it has no more connections. + bool groupInterRemove = false; + if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true; + + if (groupInterRemove) { + // get the GroupInterface from interface item + ConnectedInterface* groupInter = groupIfaceItem->refInter; + // remove interface from GroupItem, and delete it. + groupItem->removeInterfaceItem(groupIfaceItem); + // get the parent BoxItem of GroupItem if it exists. + BoxItem* parent2Item = groupItem->getParentItem(); + if (parent2Item != NULL) { + InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter); + // remove interface intem in parent BoxItem + parent2Item->removeInterfaceItem(group2IfaceItem); + } + // remove GroupInterface in the graph. + groupInter->getOwner()->removeInterface(groupInter); } - groupInter->getOwner()->removeInterface(groupInter); } } -void Dispatcher::showBlocksLibrary(){ - cout << "showing block library" << endl; - mainWindow->getLibrary()->show(); - mainWindow->getLibrary()->raise(); -} - -void Dispatcher::showProperties(InterfaceItem *inter) -{ - new InterfacePropertiesWindow(inter); -} - -/* connectInterToGroup() : - The only way for a block (functional of group) within a GroupItem to be connected - to the latter is to right-click on one of its interfaces and to choose "connect to group". - That action will create a new InterfaceItem on the GroupItem and a connectionItem between the - interfaces. -*/ -void Dispatcher::connectInterToGroup(InterfaceItem *item){ +void Dispatcher::connectBoxItemClock(Context context, BoxItem *item, QString clkName, int idGen) throw(Exception) { - // getting the GroupBlock and GroupItem that are parent of the block that owns item - ConnectedInterface *refInter = item->refInter; - cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl; - GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent()); - cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl; - GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem(); + static QString fctName = "Dispatcher::connectBoxItemClock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <getName()+"_group",refInter->getDirection(),refInter->getLevel()); - groupInter->setType(refInter->getType()); - groupInter->setWidth(refInter->getWidth()); - groupInter->setPurpose(refInter->getPurpose()); - parentItem->getRefBlock()->addInterface(groupInter); + InterfaceItem* fromIfaceItemClk = NULL; + InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName); + GroupItem* parentGroup = item->getScene()->getGroupItem(); + BoxItem* clkrstItem = NULL; - // connect both interface - bool ok = true; - if (refInter->getDirection() == AbstractInterface::Output) { - ok = refInter->connectTo(groupInter); - ok = ok & groupInter->connectFrom(refInter); + if (parentGroup->getRefBlock()->isTopGroupBlock()) { + QString genName = "clkrstgen_" + QString::number(idGen); + clkrstItem = item->getScene()->searchBoxItemByName(genName); + if (clkrstItem == NULL) { + throw(Exception(IFACE_TOP_NOCLKRSTGEN)); + } + else { + fromIfaceItemClk = clkrstItem->searchInterfaceItemByName("clk"); + } + cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to clk of " << qPrintable(genName) << endl; } - else if (refInter->getDirection() == AbstractInterface::Input) { - ok = groupInter->connectTo(refInter); - ok = ok & refInter->connectFrom(groupInter); + else { + // searching for ext_clk_idGen + QString name = "ext_clk_"+QString::number(idGen); + fromIfaceItemClk = parentGroup->searchInterfaceItemByName(name); + cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to " << qPrintable(name) << " of parent group " << qPrintable(parentGroup->getRefBlock()->getName()) << endl; } - else if (refInter->getDirection() == AbstractInterface::InOut) { - ok = refInter->connectTo(groupInter); - ok = ok & groupInter->connectFrom(refInter); - ok = ok & groupInter->connectTo(refInter); - ok = ok & refInter->connectFrom(groupInter); + + if (fromIfaceItemClk == NULL) { + throw(Exception(IFACE_GROUP_NOCLKRST)); } - if (!ok) { - cerr << "abnormal case while connecting a block iface to its parent group" << endl; + else { + createConnection(context, fromIfaceItemClk, toIfaceItemClk, false); + cout << "connection done." << endl; } - // creating/adding the group interface in the current scene model, and connection item - InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params); - parentItem->addInterface(groupIfaceItem,true); +} - parentItem->getScene()->createConnectionItem(item, groupIfaceItem); +void Dispatcher::connectBoxItemReset(Context context, BoxItem *item, QString rstName, int idGen) throw(Exception) { - // if groupItem is not topGroup, must also add a new interface to the parent BlockItem - BoxItem* parent2Item = parentItem->getParentItem(); - if(parent2Item != NULL){ - InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params); - parent2Item->addInterface(blockIfaceItem,true); + static QString fctName = "Dispatcher::connectBoxItemReset()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(rstName); + GroupItem* parentGroup = item->getScene()->getGroupItem(); + BoxItem* clkrstItem = NULL; - parentItem->getScene()->updateConnectionItemsShape(); - unselectAllItems(); - params->unsaveModif = true; - + if (parentGroup->getRefBlock()->isTopGroupBlock()) { + QString genName = "clkrstgen_" + QString::number(idGen); + clkrstItem = item->getScene()->searchBoxItemByName(genName); + if (clkrstItem == NULL) { + throw(Exception(IFACE_TOP_NOCLKRSTGEN)); + } + else { + fromIfaceItemRst = clkrstItem->searchInterfaceItemByName("reset"); + } + cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to reset of " << qPrintable(genName) << endl; + } + else { + // searching for ext_rst_idGen + QString name = "ext_rst_"+QString::number(idGen); + fromIfaceItemRst = parentGroup->searchInterfaceItemByName(name); + cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to " << qPrintable(name) << " of parent group " << qPrintable(parentGroup->getRefBlock()->getName()) << endl; + } + if (fromIfaceItemRst == NULL) { + throw(Exception(IFACE_GROUP_NOCLKRST)); + } + else { + createConnection(context, fromIfaceItemRst, toIfaceItemRst, false); + cout << "connection done." << endl; + } } -void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) { - static QString fctName = "Dispatcher::disconnectInterFromGroup()"; +void Dispatcher::connectStimuliItemClock(Context context, StimuliItem *item, QString clkName, int idGen) throw(Exception) { + + static QString fctName = "Dispatcher::connectStimuliItemClock()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <refInter; - ConnectedInterface *groupInter = NULL; - GroupBlock* parentGroup = AB_TO_GRP(refInter->getOwner()->getParent()); - GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem(); - - // removing the connection from graph -#ifdef DEBUG - cout << "removing connections from graph ..." ; -#endif + InterfaceItem* fromIfaceItemClk = NULL; + InterfaceItem* toIfaceItemClk = item->searchInterfaceItemByName(clkName); + BoxItem* clkrstItem = NULL; - if (refInter->getDirection() == AbstractInterface::Output) { - groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to - refInter->removeConnectedTo(groupInter); - groupInter->clearConnectedFrom(); - } - else if (refInter->getDirection() == AbstractInterface::Input) { - groupInter = refInter->getConnectedFrom(); - refInter->clearConnectedFrom(); - groupInter->clearConnectedTo(); + QString genName = "clkrstgen_" + QString::number(idGen); + clkrstItem = item->getScene()->searchBoxItemByName(genName); + if (clkrstItem == NULL) { + throw(Exception(IFACE_TOP_NOCLKRSTGEN)); } - else if (refInter->getDirection() == AbstractInterface::InOut) { - groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to - refInter->clearConnectedTo(); - refInter->clearConnectedFrom(); - groupInter->clearConnectedTo(); - groupInter->clearConnectedFrom(); + else { + fromIfaceItemClk = clkrstItem->searchInterfaceItemByName("clk"); } -#ifdef DEBUG - cout << "done." << endl ; -#endif + cout << "connecting clock of " << qPrintable(item->getRefBlock()->getName()) << " to clock of " << qPrintable(genName) << endl; - if (groupInter == NULL) { - cerr << "abnormal case 1 while removing an interface item of a block, linked to a parent group" << endl; + if (fromIfaceItemClk == NULL) { + throw(Exception(IFACE_GROUP_NOCLKRST)); + } + else { + createConnection(context, fromIfaceItemClk, toIfaceItemClk, false); + cout << "connection done." << endl; } +} -#ifdef DEBUG - cout << "getting group interface item, and connection item ..." ; +void Dispatcher::connectStimuliItemReset(Context context, StimuliItem *item, QString rstName, int idGen) throw(Exception) { + static QString fctName = "Dispatcher::connectStimuliItemReset()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <searchInterfaceItemByName(rstName); + BoxItem* clkrstItem = NULL; - InterfaceItem* groupIfaceItem = parentItem->searchInterfaceByRef(groupInter); - if (groupIfaceItem == NULL) { - cerr << "abnormal case 2 while removing an interface item of a block, linked to a parent group" << endl; + QString genName = "clkrstgen_" + QString::number(idGen); + clkrstItem = item->getScene()->searchBoxItemByName(genName); + if (clkrstItem == NULL) { + throw(Exception(IFACE_TOP_NOCLKRSTGEN)); } - ConnectionItem* conn = parentItem->getScene()->searchConnectionItem(item,groupIfaceItem); - if (conn == NULL) { - cerr << "abnormal case 3 while removing an interface item of a block, linked to a parent group" << endl; + else { + fromIfaceItemRst = clkrstItem->searchInterfaceItemByName("reset"); } -#ifdef DEBUG - cout << "done." << endl ; -#endif + cout << "connecting reset of " << qPrintable(item->getRefBlock()->getName()) << " to reset of " << qPrintable(genName) << endl; - // removing the interface group item from the group item, and the connection item -#ifdef DEBUG - cout << "removing group interface item, and connection item ..." ; -#endif + if (fromIfaceItemRst == NULL) { + throw(Exception(IFACE_GROUP_NOCLKRST)); + } + else { + createConnection(context, fromIfaceItemRst, toIfaceItemRst, false); + cout << "connection done." << endl; + } +} - item->removeConnectionItem(conn); - groupIfaceItem->removeConnectionItem(conn); - parentItem->removeInterface(groupIfaceItem); // CAUTION : this deletes the interface item. - parentItem->getScene()->removeConnectionItem(conn); -#ifdef DEBUG - cout << "done." << endl ; + +void Dispatcher::showBlocksLibrary(){ + cout << "showing block library" << endl; + mainWindow->getLibrary()->show(); + mainWindow->getLibrary()->raise(); +} + +void Dispatcher::showProperties(Context context, InterfaceItem *inter) { + + static QString fctName = "Dispatcher::showProperties()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <exec(); +} + +/* connectInterToGroup() : + The only way for a block (functional of group) within a GroupItem to be connected + to the latter is to right-click on one of its interfaces and to choose "connect to group". + That action will create a new InterfaceItem on the GroupItem and a connectionItem between the + interfaces. +*/ +void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){ + + static QString fctName = "Dispatcher::connectInterToGroup()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <refInter; + cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl; + GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent()); + cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl; + GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem(); + + // creating/adding the group interface in the graph model + GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose()); + parentItem->getRefBlock()->addInterface(groupInter); + // creating/adding the group control interface in the graph model if the purpose is data + if (refInter->getPurpose() == AbstractInterface::Data) { + GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control); + groupCtlInter->setAssociatedIface(groupInter); + parentItem->getRefBlock()->addInterface(groupCtlInter); + } + // creating/adding the group interface in the current scene model, and connection item + InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params); + parentItem->addInterfaceItem(groupIfaceItem,true); + + // creating the connection, in graph and with an item + /* NOTE: + Since the group interface is for now unconnected, it is impossible to determine + its clock domain. Thus, the connection must be created without testing the clock domain + consistency. For that, we cheat by changing the context to Load because it implies no clock test. + */ + createConnection(Load, item, groupIfaceItem); + // if groupItem is not topGroup, must also add a new interface to the parent BlockItem BoxItem* parent2Item = parentItem->getParentItem(); - if (parent2Item != NULL) { - InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter); - parent2Item->removeInterface(group2IfaceItem); + if(parent2Item != NULL){ + InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params); + parent2Item->addInterfaceItem(blockIfaceItem,true); } -#ifdef DEBUG - cout << "done." << endl ; -#endif - // removing the interface group from the group -#ifdef DEBUG - cout << "removing group interface ..." ; -#endif - parentGroup->removeInterface(groupInter); -#ifdef DEBUG - cout << "done." << endl ; -#endif + parentItem->getScene()->updateConnectionItemsShape(); + unselectAllItems(context); + params->unsaveModif = true; } -void Dispatcher::removeBlockInterface(InterfaceItem *item) { + +void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) { static QString fctName = "Dispatcher::removeBlockInterface()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <connections) { - removeConnection(conn); + removeConnection(context, conn); } ConnectedInterface* ref = item->refInter; - item->getOwner()->removeInterface(item); + item->getOwner()->removeInterfaceItem(item); FunctionalBlock* fun = AB_TO_FUN(ref->getOwner()); fun->removeInterface(ref); } -void Dispatcher::removeGroupInterface(InterfaceItem *item) { +void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) { static QString fctName = "Dispatcher::removeGroupInterface()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <connections.at(0); - if (conn->getFromInterfaceItem() == item) { - disconnectInterFromGroup(conn->getToInterfaceItem()); - } - else { - disconnectInterFromGroup(conn->getFromInterfaceItem()); + foreach(ConnectionItem* conn, item->connections) { + removeConnection(context, conn); } } @@ -981,7 +1686,7 @@ QMap Dispatcher::getAllGroupNames() { return list; } -GroupScene* Dispatcher::searchSceneById(int id) { +GroupScene* Dispatcher::getSceneById(int id) { foreach(GroupWidget *group, groupList){ if(group->getScene()->getId() == id) return group->getScene(); @@ -990,7 +1695,7 @@ GroupScene* Dispatcher::searchSceneById(int id) { return NULL; } -GroupItem *Dispatcher::searchGroupItemById(int id) { +GroupItem *Dispatcher::getGroupItemById(int id) { foreach(GroupWidget *group, groupList) { GroupScene* scene = group->getScene(); if (scene->getGroupItem()->getId() == id) return scene->getGroupItem(); @@ -999,11 +1704,11 @@ GroupItem *Dispatcher::searchGroupItemById(int id) { return NULL; } -BoxItem *Dispatcher::searchBlockItemById(int id) { +BoxItem *Dispatcher::getBoxItemById(int id) { foreach(GroupWidget *group, groupList) { GroupScene* scene = group->getScene(); - foreach(BoxItem *item, scene->getBlockItems()){ + foreach(BoxItem *item, scene->getBoxItems()){ if(item->getId() == id){ return item; } @@ -1013,7 +1718,7 @@ BoxItem *Dispatcher::searchBlockItemById(int id) { return NULL; } -InterfaceItem* Dispatcher::searchInterfaceItemById(int id) { +InterfaceItem* Dispatcher::getInterfaceItemById(int id) { foreach(GroupWidget *group, groupList) { @@ -1024,7 +1729,7 @@ InterfaceItem* Dispatcher::searchInterfaceItemById(int id) { return item; } } - foreach(BoxItem *block, scene->getBlockItems()){ + foreach(BoxItem *block, scene->getBoxItems()){ foreach(InterfaceItem *item, block->getInterfaces()){ if(item->getId() == id){ return item; @@ -1036,3 +1741,37 @@ InterfaceItem* Dispatcher::searchInterfaceItemById(int id) { return NULL; } +void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) { + static QString fctName = "Dispatcher::findGraphModifications()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + /* NB: only called in Design context */ + if (context != Design) { + cout << "Abnormal case: call to " <computeAdmittanceDelays(); + // get the block item that is associated to block + BoxItem* toBlockItem = params->blockToItem.value(block); + + /* VERSION 1: just add delays if needed */ + QMap* > delays = block->getAdmittanceDelays(); + QMapIterator* > iterD(delays); + while (iterD.hasNext()) { + iterD.next(); + QList* delay = iterD.value(); + if (delay->at(0) > 0) { + // create delay and associate it to the connected input + + ConnectedInterface* toIface = AI_TO_CON(iterD.key()); + AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0)); + cout << "modify input of " << qPrintable(toIface->getName()) << endl; + toIface->setInputModifier(mod); + // repaint + toBlockItem->update(); + } + } +} +