// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2016, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | K n i k - G l o b a l R o u t e r | // | | // | Author : Jean-Paul Chaput | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./GraphicKnikEngine.cpp" | // +-----------------------------------------------------------------+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Knik { using namespace std; using Hurricane::Warning; using Hurricane::Graphics; using CRL::AllianceFramework; // ------------------------------------------------------------------- // Class : "CRL::GraphicKnikEngine". size_t GraphicKnikEngine::_references = 0; GraphicKnikEngine* GraphicKnikEngine::_singleton = NULL; void GraphicKnikEngine::initKnikEdges ( CellWidget* widget ) { widget->getDrawingPlanes().setPen ( Qt::NoPen ); } void GraphicKnikEngine::drawKnikEdges ( CellWidget* widget , const Go* go , const BasicLayer* basicLayer , const Box& box , const Transformation& transformation ) { const Edge* edge = dynamic_cast(go); if ( edge ) { unsigned int occupancy = 255; if ( edge->getRealOccupancy() < edge->getCapacity() ) occupancy = (unsigned int)( 255.0 * ( (float)edge->getRealOccupancy() / (float)edge->getCapacity() ) ); QPainter& painter = widget->getPainter(); if ( edge->getRealOccupancy() > edge->getCapacity() ) { QColor color (Qt::cyan); painter.setPen (DisplayStyle::darken(color,widget->getDarkening())); } painter.setBrush ( Graphics::getColorScale(ColorScale::Fire).getBrush(occupancy,widget->getDarkening()) ); painter.drawRect ( widget->dbuToScreenRect(edge->getBoundingBox(), false) ); painter.setPen(Qt::NoPen); // affichage des infos de l'arete if ( edge->hasInfo() ) { QColor color (Qt::blue); painter.setPen (DisplayStyle::darken(color,widget->getDarkening())); QFont font; font.setBold(true); font.setPointSize(10); painter.setFont(font); //QString text = QString("%1%2%3").arg(edge->getConnexID()).arg(",").arg(edge->getConstCost()); QString text = QString("%1").arg(edge->getConnexID()); //Point fromPos = edge->getFrom()->getPosition(); //Point toPos = edge->getTo()->getPosition(); //painter.drawText ( widget->dbuToDisplayPoint ( (fromPos.getX()+toPos.getX())/2+DbU::lambda(0.5), (fromPos.getY()+toPos.getY())/2+DbU::lambda(0.5) ), text ); if ( edge->isVertical() ) { painter.save(); Box bbox = edge->getBoundingBox(); painter.translate (widget->dbuToScreenPoint(bbox.getXMin(), bbox.getYMin())); painter.rotate(-90); painter.drawText (QRect(0,0,widget->dbuToScreenLength(bbox.getHeight()),widget->dbuToScreenLength(bbox.getWidth())), text, QTextOption(Qt::AlignCenter)); //painter.drawText (0, 0, text); painter.restore(); } else painter.drawText ( widget->dbuToScreenRect ( edge->getBoundingBox(),false ), text, QTextOption (Qt::AlignCenter) ); painter.setPen(Qt::NoPen); } } } void GraphicKnikEngine::initKnikVertex ( CellWidget* widget ) { //widget->getDrawingPlanes().setPen ( Qt::NoPen ); //widget->getDrawingPlanes().setBrush ( color.darker(widget->getDarkening()) ); } void GraphicKnikEngine::drawKnikVertex ( CellWidget* widget , const Go* go , const BasicLayer* basicLayer , const Box& box , const Transformation& transformation ) { const Vertex* vertex = dynamic_cast(go); if ( vertex ) { QPainter& painter = widget->getPainter(); QColor color = Qt::darkRed; QPen pen (DisplayStyle::darken(color,widget->getDarkening())); pen.setWidth(2); widget->setPen(pen); painter.drawEllipse ( widget->dbuToScreenRect ( vertex->getBoundingBox(), false ) ); if ( vertex->hasInfo() ) { QColor color (Qt::blue); painter.setPen (DisplayStyle::darken(color,widget->getDarkening())); QFont font; font.setBold(true); font.setPointSize(10); painter.setFont(font); //QString text = QString("%1%2%3").arg(edge->getConnexID()).arg(",").arg(edge->getConstCost()); QString text = QString("%1 / %2").arg(vertex->getConnexID()).arg(vertex->getDistance()); //Point center = vertex->getPosition(); Box textBox = Box(vertex->getXMin(), vertex->getYMin(), vertex->getXMax(), vertex->getYMax()); painter.drawText ( widget->dbuToScreenRect ( textBox,false ), text, QTextOption (Qt::AlignCenter) ); painter.setPen(Qt::NoPen); } } } KnikEngine* GraphicKnikEngine::createEngine ( unsigned int mode ) { Cell* cell = getCell (); KnikEngine* knik = KnikEngine::get ( cell ); if ( !knik ) { if ( cell->getRubbers().getFirst() == NULL ) cell->flattenNets ( ((mode==BuildSolution)?Cell::Flags::BuildRings:0) ); knik = KnikEngine::create ( cell , _congestion , _preCongestion , _benchMode , _useSegments , _edgeCost ); if ( mode == LoadSolution ) knik->createRoutingGraph (); } //else // cerr << Warning("%s already has a Knik engine.",getString(cell).c_str()) << endl; return knik; } void GraphicKnikEngine::flattenNets () { Cell* cell = getCell (); //emit cellPreModificated(); cell->flattenNets ( Cell::Flags::BuildRings ); //emit cellPostModificated(); } void GraphicKnikEngine::run () { KnikEngine* knik = createEngine ( BuildSolution ); if ( !knik ) return; //emit cellPreModificated (); map excludedNets; knik->run ( excludedNets ); //emit cellPostModificated (); } void GraphicKnikEngine::route () { KnikEngine* knik = createEngine ( BuildSolution ); if ( !knik ) return; //emit cellPreModificated (); map excludedNets; knik->Route ( excludedNets ); //emit cellPostModificated (); } bool GraphicKnikEngine::analyse () { Cell* cell = getCell (); //emit cellPreModificated(); bool done = false; KnikEngine* knik = KnikEngine::get ( cell ); if ( knik ) { done = knik->analyseRouting(); } //emit cellPostModificated(); return done; } void GraphicKnikEngine::unroute () { Cell* cell = getCell (); //emit cellPreModificated(); KnikEngine* knik = KnikEngine::get ( cell ); if ( knik ) knik->unrouteOvSegments(); //emit cellPostModificated(); } void GraphicKnikEngine::reroute () { Cell* cell = getCell (); //emit cellPreModificated(); KnikEngine* knik = KnikEngine::get ( cell ); if ( knik ) knik->reroute(); //emit cellPostModificated(); } void GraphicKnikEngine::saveSolution () { Cell* cell = getCell (); //emit cellPreModificated(); KnikEngine* knik = KnikEngine::get ( cell ); if ( knik ) knik->saveSolution(); //emit cellPostModificated(); } void GraphicKnikEngine::loadSolution () { KnikEngine* knik = createEngine ( LoadSolution ); if ( !knik ) return; //emit cellPreModificated(); knik->loadSolution(); //emit cellPostModificated(); } void GraphicKnikEngine::addToMenu ( CellViewer* viewer ) { assert ( _viewer == NULL ); _viewer = viewer; QMenu* prMenu = _viewer->findChild("viewer.menuBar.placeAndRoute"); QMenu* stepMenu = _viewer->findChild("viewer.menuBar.placeAndRoute.stepByStep"); if ( !prMenu ) { QMenuBar* menuBar = _viewer->findChild("viewer.menuBar"); if ( !menuBar ) { cerr << Warning("GraphicKnikEngine::addToMenu() - No MenuBar in parent widget.") << endl; return; } prMenu = menuBar->addMenu ( tr("P&&R") ); prMenu->setObjectName ( "viewer.menuBar.placeAndRoute" ); stepMenu = prMenu->addMenu ( tr("&Step by Step") ); stepMenu->setObjectName ( "viewer.menuBar.placeAndRoute.stepByStep" ); prMenu->addSeparator (); } QAction* gRunAction = _viewer->findChild("viewer.menuBar.placeAndRoute.globalRoute"); if ( gRunAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in.") << endl; else { gRunAction = new QAction ( tr("Knik - &Global Route"), _viewer ); gRunAction->setObjectName ( "viewer.menuBar.placeAndRoute.globalRoute" ); gRunAction->setStatusTip ( tr("Run the Knik global router") ); gRunAction->setVisible ( true ); prMenu->addAction ( gRunAction ); connect ( gRunAction, SIGNAL(triggered()), this, SLOT(run()) ); } QAction* gFlattenAction = _viewer->findChild("viewer.menuBar.placeAndRoute.flattenNets"); if ( gFlattenAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in.") << endl; else { gFlattenAction = new QAction ( tr("Knik - &Prepare nets"), _viewer ); gFlattenAction->setObjectName ( "viewer.menuBar.placeAndRoute.flattenNets" ); gFlattenAction->setStatusTip ( tr("Prepare nets for routing") ); gFlattenAction->setVisible ( true ); stepMenu->addAction ( gFlattenAction ); connect ( gFlattenAction, SIGNAL(triggered()), this, SLOT(flattenNets()) ); } QAction* gRouteAction = _viewer->findChild("viewer.menuBar.placeAndRoute.simpleGlobalRoute"); if ( gRouteAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in.") << endl; else { gRouteAction = new QAction ( tr("Knik - &Simple Global Route (no ripup)"), _viewer ); gRouteAction->setObjectName ( "viewer.menuBar.placeAndRoute.simpleGlobalRoute" ); gRouteAction->setStatusTip ( tr("Run the Knik global router") ); gRouteAction->setVisible ( true ); stepMenu->addAction ( gRouteAction ); connect ( gRouteAction, SIGNAL(triggered()), this, SLOT(route()) ); } QAction* gAnalyseAction = _viewer->findChild("viewer.menuBar.placeAndRoute.analyse"); if ( gAnalyseAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in (analyse function).") << endl; else { gAnalyseAction = new QAction ( tr("Knik - &Analyse routing"), _viewer ); gAnalyseAction->setObjectName ( "viewer.menuBar.placeAndRoute.analyse" ); gAnalyseAction->setStatusTip ( tr("Analyse routing done by Knik") ); gAnalyseAction->setVisible ( true ); stepMenu->addAction ( gAnalyseAction ); connect ( gAnalyseAction, SIGNAL(triggered()), this, SLOT(analyse()) ); } QAction* gUnrouteAction = _viewer->findChild("viewer.menuBar.placeAndRoute.unroute"); if ( gUnrouteAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in (unroute function).") << endl; else { gUnrouteAction = new QAction ( tr("Knik - &Unroute overflowed segments"), _viewer ); gUnrouteAction->setObjectName ( "viewer.menuBar.placeAndRoute.unroute" ); gUnrouteAction->setStatusTip ( tr("Unroute overflowed segments") ); gUnrouteAction->setVisible ( true ); stepMenu->addAction ( gUnrouteAction ); connect ( gUnrouteAction, SIGNAL(triggered()), this, SLOT(unroute()) ); } QAction* gRerouteAction = _viewer->findChild("viewer.menuBar.placeAndRoute.reroute"); if ( gRerouteAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in (reroute function).") << endl; else { gRerouteAction = new QAction ( tr("Knik - &Reroute"), _viewer ); gRerouteAction->setObjectName ( "viewer.menuBar.placeAndRoute.reroute" ); gRerouteAction->setStatusTip ( tr("Reroute") ); gRerouteAction->setVisible ( true ); stepMenu->addAction ( gRerouteAction ); connect ( gRerouteAction, SIGNAL(triggered()), this, SLOT(reroute()) ); } QAction* gSaveAction = _viewer->findChild("viewer.menuBar.placeAndRoute.saveSolution"); if ( gSaveAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in (save function).") << endl; else { gSaveAction = new QAction ( tr("Knik - &Save global routing"), _viewer ); gSaveAction->setObjectName ( "viewer.menuBar.placeAndRoute.saveSolution" ); gSaveAction->setStatusTip ( tr("Save global routing (.kgr file)") ); gSaveAction->setVisible ( true ); stepMenu->addAction ( gSaveAction ); connect ( gSaveAction, SIGNAL(triggered()), this, SLOT(saveSolution()) ); } QAction* gLoadAction = _viewer->findChild("viewer.menuBar.placeAndRoute.loadSolution"); if ( gLoadAction ) cerr << Warning("GraphicKnikEngine::addToMenu() - Knik global router already hooked in (load function).") << endl; else { gLoadAction = new QAction ( tr("Knik - &Load global routing"), _viewer ); gLoadAction->setObjectName ( "viewer.menuBar.placeAndRoute.loadSolution" ); gLoadAction->setStatusTip ( tr("Load global routing (.kgr file)") ); gLoadAction->setVisible ( true ); stepMenu->addAction ( gLoadAction ); connect ( gLoadAction, SIGNAL(triggered()), this, SLOT(loadSolution()) ); } // fin du sous menu } const Name& GraphicKnikEngine::getName () const { return KnikEngine::staticGetName (); } Cell* GraphicKnikEngine::getCell () { if ( !_viewer ) { throw Error ( "Knik: GraphicKnikEngine not bound to any Viewer." ); return NULL; } if ( !_viewer->getCell() ) { throw Error ( "Knik: No Cell is loaded into the Viewer." ); return NULL; } return _viewer->getCell(); } GraphicKnikEngine* GraphicKnikEngine::grab () { if ( !_references ) _singleton = new GraphicKnikEngine (); _references++; return _singleton; } size_t GraphicKnikEngine::release () { _references--; if ( !_references ) { delete _singleton; _singleton = NULL; } return _references; } GraphicKnikEngine::GraphicKnikEngine () : GraphicTool () , _viewer (NULL) , _congestion (1) , _preCongestion(2) , _benchMode (false) , _useSegments (true) , _edgeCost (2.5) { addDrawGo ( "Knik::Edges", initKnikEdges, drawKnikEdges ); addDrawGo ( "Knik::Vertex", initKnikVertex, drawKnikVertex ); } GraphicKnikEngine::~GraphicKnikEngine() { } } // End of Knik namespace.