// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2016-2016, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | A n a b a t i c - Global Routing Toolbox | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./GlobalRoute.cpp" | // +-----------------------------------------------------------------+ #include #include #include "hurricane/Error.h" #include "hurricane/RegularLayer.h" #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Cell.h" #include "hurricane/UpdateSession.h" #include "hurricane/DebugSession.h" #include "crlcore/RoutingGauge.h" #include "anabatic/GCell.h" #include "anabatic/Dijkstra.h" #include "anabatic/AnabaticEngine.h" namespace { using std::cerr; using std::endl; using std::setw; using std::left; using std::right; using Hurricane::DbU; using Anabatic::Edge; using Anabatic::Vertex; class DigitalDistance { public: inline DigitalDistance ( float h, float k ); DbU::Unit operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const; private: // For an explanation of h & k parameters, see: // "KNIK, routeur global pour la plateforme Coriolis", p. 52. float _h; float _k; }; inline DigitalDistance::DigitalDistance ( float h, float k ) : _h(h), _k(k) { } DbU::Unit DigitalDistance::operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const { if (edge->getCapacity() <= 0) return Vertex::unreached; float congestion = (float)edge->getRealOccupancy() / (float)edge->getCapacity(); float congestionCost = 1.0 + _h / (1.0 + std::exp(_k * (congestion - 1.0))); float distance = (float)source->getDistance() + congestionCost * (float)edge->getDistance(); + edge->getHistoricCost(); // Edge* sourceFrom = source->getFrom(); // if (sourceFrom) { // distance += ((sourceFrom->isHorizontal() xor edge->isHorizontal()) ? 3.0 : 0.0) * (float)Edge::unity; // } cdebug_log(112,0) << "cong:" << congestion << " ccost:" << congestionCost << " digitalDistance:" << DbU::getValueString((DbU::Unit)distance) << endl; return (DbU::Unit)distance; } void computeNextHCost ( Edge* edge, float edgeHInc ) { float congestion = (float)edge->getRealOccupancy() / (float)edge->getCapacity(); float hCost = edge->getHistoricCost(); float alpha = (congestion < 1.0) ? congestion : std::exp( std::log(8)*( congestion - 1 ) ); edge->setHistoricCost( alpha * (hCost + ((congestion < 1.0) ? 0.0 : edgeHInc) )); cdebug_log(113,0) << edge << endl; } } // Anonymous namespace. namespace Anabatic { using std::cerr; using std::cout; using std::endl; using std::setw; using std::ostringstream; using Hurricane::Error; using Hurricane::RegularLayer; using Hurricane::Component; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::Cell; using Hurricane::UpdateSession; using Hurricane::DebugSession; using CRL::RoutingGauge; using CRL::RoutingLayerGauge; // ------------------------------------------------------------------- // Class : "Anabatic::AnabaticEngine". // // Methods dedicateds to complete global routing. void AnabaticEngine::globalRoute () { Cell* cell = getCell(); cell->flattenNets( Cell::Flags::BuildRings ); cell->createRoutingPadRings( Cell::Flags::BuildRings ); //DebugSession::addToTrace( cell->getNet("ra(2)") ); //DebugSession::addToTrace( cell->getNet("alu_out(3)") ); //DebugSession::addToTrace( cell->getNet("imuxe.not_i(1)") ); //DebugSession::addToTrace( cell->getNet("r(0)") ); //DebugSession::addToTrace( cell->getNet("a_from_pads(0)") ); //DebugSession::addToTrace( cell->getNet("ialu.not_aux104") ); //DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_muxoutput(159)") ); //DebugSession::addToTrace( cell->getNet("mips_r3000_1m_dp_shift32_rshift_se_c1(3)") ); startMeasures(); UpdateSession::open(); if (getGCells().size() == 1) { cmess1 << " o Building regular grid..." << endl; getSouthWestGCell()->doGrid(); } else { cmess1 << " o Reusing existing grid." << endl; } cmess1 << Dots::asInt(" - GCells" ,getGCells().size()) << endl; UpdateSession::close(); stopMeasures(); printMeasures( "Anabatic Grid" ); Session::open( this ); setupSpecialNets(); setupPreRouteds (); setupNetDatas(); Session::close(); startMeasures(); cmess1 << " o Running global routing..." << endl; float edgeHInc = getConfiguration()->getEdgeHInc(); Session::open( this ); Dijkstra* dijkstra = new Dijkstra ( this ); dijkstra->setDistance( DigitalDistance( getConfiguration()->getEdgeCostH() , getConfiguration()->getEdgeCostK() ) ); size_t iteration = 0; size_t netCount = 0; do { cmess2 << " [" << setw(3) << iteration << "] nets:"; netCount = 0; for ( NetData* netData : _netOrdering ) { if (netData->isGlobalRouted()) continue; dijkstra->load( netData->getNet() ); dijkstra->run(); ++netCount; } cmess2 << left << setw(6) << netCount << right; //Session::revalidate(); const vector& ovEdges = getOvEdges(); cmess2 << " ovEdges:" << ovEdges.size(); for ( Edge* edge : ovEdges ) computeNextHCost( edge, edgeHInc ); netCount = 0; size_t iEdge = 0; while ( iEdge < ovEdges.size() ) { Edge* edge = ovEdges[iEdge]; netCount += edge->ripup(); if (ovEdges[iEdge] == edge) { cerr << Error( "AnabaticEngine::globalRoute(): Unable to ripup enough segments of edge:\n" " %s" , getString(edge).c_str() ) << endl; ++iEdge; } } dijkstra->setSearchAreaHalo( Session::getSliceHeight()*3 ); cmess2 << " ripup:" << netCount; stopMeasures(); cmess2 << " " << setw(10) << Timer::getStringTime (_timer.getCombTime()) << " " << setw( 6) << Timer::getStringMemory(_timer.getIncrease()) << endl; startMeasures(); #if THIS_IS_A_TEST if (iteration == 0) { Net* testNet = getCell()->getNet( "ra(2)" ); DebugSession::open( testNet, 112, 120 ); if (testNet) { for ( Component* component : testNet->getComponents() ) { if (component->getId() == 23947) { Segment* segment = static_cast( component ); GCellsUnder gcells = getGCellsUnder( segment ); Contact* contact = breakAt( segment, gcells->gcellAt(2) ); cerr << "break:" << contact << endl; unify( contact ); //ripup( static_cast(component), Flags::Propagate ); //iteration = 5; //netsToRoute.insert( testNet ); break; } } } DebugSession::close(); } #endif ++iteration; } while ( (netCount > 0) and (iteration < 5) ); stopMeasures(); printMeasures( "Dijkstra" ); delete dijkstra; Session::close(); _state = EngineGlobalLoaded; } } // Anabatic namespace.