// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved // // =================================================================== // // $Id$ // // +-----------------------------------------------------------------+ // | | // | C O R I O L I S | // | K i t e - D e t a i l e d R o u t e r | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./NegociateWindow.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // +-----------------------------------------------------------------+ #include #include #include #include "hurricane/Warning.h" #include "hurricane/Bug.h" #include "hurricane/RoutingPad.h" #include "hurricane/Net.h" #include "hurricane/Cell.h" #include "crlcore/Utilities.h" #include "crlcore/AllianceFramework.h" #include "crlcore/Measures.h" #include "crlcore/Histogram.h" #include "katabatic/AutoContact.h" #include "katabatic/GCellGrid.h" #include "kite/DataNegociate.h" #include "kite/TrackElement.h" #include "kite/TrackMarker.h" #include "kite/TrackCost.h" #include "kite/Track.h" #include "kite/TrackSegment.h" #include "kite/RoutingPlane.h" #include "kite/RoutingEventQueue.h" #include "kite/RoutingEventHistory.h" #include "kite/RoutingEventLoop.h" #include "kite/NegociateWindow.h" #include "kite/KiteEngine.h" namespace { using namespace std; using namespace Hurricane; using namespace CRL; using namespace Kite; void NegociateOverlapCost ( const TrackElement* segment, TrackCost& cost ) { Interval intersect = segment->getCanonicalInterval(); if ( not intersect.intersect ( cost.getInterval() ) ) return; if ( segment->isBlockage() or segment->isFixed() ) { ltrace(200) << "Infinite cost from: " << segment << endl; cost.setInfinite (); cost.setOverlap (); cost.setHardOverlap (); cost.setBlockage (); return; } if ( cost.getInterval().getVMax() > intersect.getVMax() ) cost.setLeftOverlap(); if ( cost.getInterval().getVMin() < intersect.getVMin() ) cost.setRightOverlap(); if ( not intersect.contains(cost.getInterval()) ) intersect.intersection ( cost.getInterval() ); DataNegociate* data = segment->getDataNegociate (); if ( not data ) return; cost.mergeRipupCount ( data->getRipupCount() ); if ( segment->isLocal() ) { cost.mergeDataState ( data->getState() ); if ( data->getState() >= DataNegociate::LocalVsGlobal ) { ltrace(200) << "MaximumSlack/LocalVsGlobal for " << segment << endl; } } if ( segment->isGlobal() ) { //if ( data->getState() >= DataNegociate::ConflictSolve1 ) { cost.setOverlapGlobal(); //} } // if ( data->getRipupCount() > 3 ) { // ltrace(200) << "Infinite cost from: " << segment << endl; // cost.setFixed (); // cost.setInfinite (); // cost.setOverlap (); // cost.setHardOverlap (); // return; // } cost.setOverlap (); if ( segment->isLocal() or (Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) < 3) ) cost.incTerminals ( data->getCost().getTerminals()*100 ); cost.incDelta ( intersect.getSize() ); } void loadRoutingPads ( NegociateWindow* nw ) { AllianceFramework* af = AllianceFramework::get (); RoutingGauge* rg = nw->getKiteEngine()->getRoutingGauge(); forEach ( Net*, inet, nw->getCell()->getNets() ) { if ( inet->getType() == Net::Type::POWER ) continue; if ( inet->getType() == Net::Type::GROUND ) continue; if ( inet->getType() == Net::Type::CLOCK ) continue; if ( af->isBLOCKAGE(inet->getName()) ) continue; forEach ( RoutingPad*, irp, inet->getRoutingPads() ) { size_t depth = rg->getLayerDepth(irp->getLayer()); if ( depth > 0 ) continue; if ( depth == 0 ) { TrackMarker::create ( *irp, 1 ); } } } } } // End of local namespace. namespace Kite { using std::cerr; using std::endl; using std::setw; using std::left; using std::right; using std::setprecision; using Hurricane::Warning; using Hurricane::Bug; using Hurricane::tab; using Hurricane::inltrace; using Hurricane::ltracein; using Hurricane::ltraceout; using Hurricane::ForEachIterator; using CRL::Histogram; using CRL::addMeasure; using Katabatic::AutoContact; // ------------------------------------------------------------------- // Class : "NegociateWindow". NegociateWindow::NegociateWindow ( KiteEngine* kite ) : _slowMotion (0) , _interrupt (false) , _kite (kite) , _gcells () , _segments () , _eventQueue () , _eventHistory() , _eventLoop (10,50) { } NegociateWindow* NegociateWindow::create ( KiteEngine* kite ) { NegociateWindow* negociateWindow = new NegociateWindow ( kite ); return negociateWindow; } NegociateWindow::~NegociateWindow () { } void NegociateWindow::destroy () { delete this; } Cell* NegociateWindow::getCell () const { return _kite->getCell(); } void NegociateWindow::setGCells ( const Katabatic::GCellVector& gcells ) { _gcells = gcells; //sort ( _gcells.begin(), _gcells.end(), Katabatic::GCell::CompareGCellById() ); loadRoutingPads ( this ); Session::revalidate (); TrackElement* segment; TrackElementLut lut = Session::getKiteEngine()->_getTrackElementLut(); TrackElementLut::iterator it = lut.begin (); for ( ; it != lut.end() ; it++ ) { segment = it->second; segment->getDataNegociate()->update(); } _statistics.setGCellsCount ( _gcells.size() ); } void NegociateWindow::addInsertEvent ( TrackElement* segment, unsigned int level ) { DataNegociate* data = segment->getDataNegociate(); if ( not data or not data->hasRoutingEvent() ) _eventQueue.add ( segment, level ); else cerr << Bug("NegociateWidow::addInsertEvent(): Try to adds twice the same TrackElement event." "\n %p:%s." ,(void*)segment->base()->base() ,getString(segment).c_str() ) << endl; } TrackElement* NegociateWindow::addTrackSegment ( AutoSegment* autoSegment, bool loading ) { ltrace(200) << "NegociateWindow::addTrackSegment() - " << autoSegment << endl; ltracein(159); // Special case: fixed AutoSegments must not interfere with blockages. // Ugly: uses of getExtensionCap(). if ( autoSegment->isFixed() ) { RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer()); Track* track = plane->getTrackByPosition ( autoSegment->getAxis() ); size_t begin; size_t end; Interval fixedSpan; Interval blockageSpan; autoSegment->getCanonical ( fixedSpan ); fixedSpan.inflate ( Session::getExtensionCap()-1 ); track->getOverlapBounds ( fixedSpan, begin, end ); for ( ; (begin < end) ; begin++ ) { TrackElement* other = track->getSegment(begin); ltrace(200) << "| overlap: " << other << endl; if ( not other->isBlockage() ) continue; other->getCanonical ( blockageSpan ); blockageSpan.inflate(Session::getExtensionCap()); ltrace(200) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl; if ( not fixedSpan.intersect(blockageSpan) ) continue; // Overlap between fixed & blockage. ltrace(200) << "* Blockage overlap: " << autoSegment << endl; Session::destroyRequest ( autoSegment ); cerr << Warning("Overlap between fixed %s and blockage at %s." ,getString(autoSegment).c_str(),getString(blockageSpan).c_str()) << endl; return NULL; } } Interval span; autoSegment = autoSegment->getCanonical ( span ); bool created; TrackElement* trackSegment = TrackSegment::create ( autoSegment, NULL, created ); if ( not loading ) ltrace(159) << "* lookup: " << autoSegment << endl; if ( created ) { ltrace(159) << "* " << trackSegment << endl; RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer()); Track* track = plane->getTrackByPosition ( autoSegment->getAxis() ); Interval uside = autoSegment->getAutoSource()->getGCell()->getUSide ( Constant::perpandicular(autoSegment->getDirection())/*, false */); if ( track->getAxis() > uside.getVMax() ) track = track->getPrevious(); if ( track->getAxis() < uside.getVMin() ) track = track->getNext(); trackSegment->setAxis ( track->getAxis(), Katabatic::Realignate|Katabatic::AxisSet ); trackSegment->invalidate (); if ( trackSegment->isFixed() ) { Session::addInsertEvent ( trackSegment, track ); } else { _segments.push_back ( trackSegment ); } } if ( not created and not loading ) { ltrace(200) << "TrackSegment already exists (and not in loading stage)." << endl; } ltraceout(159); return trackSegment; } double NegociateWindow::computeWirelength () { set accounteds; double totalWL = 0.0; for ( size_t igcell=0 ; igcell<_gcells.size() ; ++igcell ) { double gcellWL = 0.0; Segment* segment; TrackElement* trackSegment; vector* contacts = _gcells[igcell]->getContacts(); for ( size_t i=0 ; isize() ; i++ ) { forEach ( Hook*, ihook, (*contacts)[i]->getBodyHook()->getSlaveHooks() ) { Hook* sourceHook = dynamic_cast(*ihook); if ( not sourceHook ) continue; segment = dynamic_cast(sourceHook->getComponent()); trackSegment = Session::lookup ( segment ); if ( trackSegment ) { if ( accounteds.find(trackSegment) != accounteds.end() ) continue; accounteds.insert ( trackSegment ); gcellWL += DbU::getLambda ( trackSegment->getLength() ); } } } // Partial sum to limit rounding errors. totalWL += gcellWL; } return totalWL; } void NegociateWindow::_createRouting ( Katabatic::GCell* gcell ) { ltrace(200) << "NegociateWindow::_createRouting() - " << gcell << endl; ltracein(200); Segment* segment; AutoSegment* autoSegment; ltrace(149) << "AutoSegments from AutoContacts" << endl; vector* contacts = gcell->getContacts(); for ( size_t i=0 ; isize() ; i++ ) { forEach ( Component*, component, (*contacts)[i]->getSlaveComponents() ) { segment = dynamic_cast(*component); autoSegment = Session::base()->lookup ( segment ); ltrace(149) << autoSegment << endl; if ( autoSegment and autoSegment->isCanonical() ) { addTrackSegment ( autoSegment, true ); } } } ltrace(149) << "_segments.size():" << _segments.size() << endl; ltraceout(200); } size_t NegociateWindow::_negociate () { ltrace(150) << "NegociateWindow::_negociate() - " << _segments.size() << endl; ltracein(149); unsigned long limit = _kite->getEventsLimit(); _eventHistory.clear(); _eventQueue.load ( _segments ); size_t count = 0; while ( not _eventQueue.empty() and not isInterrupted() ) { RoutingEvent* event = _eventQueue.pop (); if (tty::enabled()) { cmess2 << " " << tty::cr; cmess2.flush (); } else { cmess2 << " getEventLevel() << ":" << event->getPriority() << "> " << event->getSegment() //<< "> @" << DbU::getValueString(event->getSegment()->getAxis()) //<< " id:" << event->getSegment()->getId() //<< " " << event->getSegment()->getNet()->getName() << endl; cmess2.flush(); } event->process ( _eventQueue, _eventHistory, _eventLoop ); if ( RoutingEvent::getProcesseds() >= limit ) setInterrupt ( true ); count++; } if (count and tty::enabled()) cmess1 << endl; count = 0; ltrace(200) << "Dumping history." << endl; for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) { RoutingEvent* event = _eventHistory.getNth(i); ltrace(200) << (void*)event << " [" << (event->isCloned ()?"C":"-") << (event->isDisabled ()?"d":"-") << (event->isUnimplemented()?"u":"-") << "] " << event->getSegment() << endl; if ( !event->isCloned() and event->isUnimplemented() ) { count++; event->setProcessed ( false ); event->setMode ( RoutingEvent::PostPack ); event->process ( _eventQueue, _eventHistory, _eventLoop ); if (tty::enabled()) { cmess1 << " " << tty::cr; cmess1.flush (); } else { cmess1 << " " << endl; } } } if (count and tty::enabled()) cmess1 << endl; size_t eventsCount = _eventHistory.size(); _eventHistory.clear(); _eventQueue.clear(); if ( RoutingEvent::getAllocateds() > 0 ) { cerr << Bug("%d events remains after clear.",RoutingEvent::getAllocateds()) << endl; } // if ( _slowMotion && getCellWidget() ) { // Session::close (); // getCellWidget()->refresh(); // Session::open ( _kiteEngine ); // } _statistics.setEventsCount ( eventsCount ); ltraceout(149); return eventsCount; } void NegociateWindow::run ( int slowMotion ) { ltrace(150) << "NegociateWindow::run()" << endl; ltracein(149); TrackElement::setOverlapCostCB ( NegociateOverlapCost ); RoutingEvent::resetProcesseds (); for ( size_t igcell=0 ; igcell<_gcells.size() ; ++igcell ) { _createRouting ( _gcells[igcell] ); } Session::revalidate (); getKiteEngine()->setMinimumWL ( computeWirelength() ); #if defined(CHECK_DATABASE) unsigned int overlaps = 0; Session::getKiteEngine()->_check(overlaps,"after _createRouting(GCell*)"); #endif _slowMotion = slowMotion; _negociate (); Session::get()->isEmpty(); # if defined(CHECK_DATABASE) _kite->_check ( overlaps, "after negociation" ); # endif ltraceout(149); } void NegociateWindow::printStatistics () const { cmess1 << " o Computing statistics." << endl; cmess1 << Dots::asSizet(" - Processeds Events Total",RoutingEvent::getProcesseds()) << endl; cmess1 << Dots::asSizet(" - Unique Events Total" ,(RoutingEvent::getProcesseds() - RoutingEvent::getCloneds())) << endl; cmess1 << Dots::asSizet(" - # of GCells",_statistics.getGCellsCount()) << endl; addMeasure( getCell(), "Events" , RoutingEvent::getProcesseds(), 12 ); addMeasure( getCell(), "UEvents", RoutingEvent::getProcesseds()-RoutingEvent::getCloneds(), 12 ); Histogram* densityHistogram = new Histogram ( 1.0, 0.1, 2 ); addMeasure( getCell(), "GCells Density Histogram", densityHistogram ); densityHistogram->setFileExtension ( ".density.histogram" ); densityHistogram->setMainTitle ( "GCell Densities" ); densityHistogram->setTitle ( "Avg. Density", 0 ); densityHistogram->setTitle ( "Peak Density", 1 ); densityHistogram->setColor ( "green", 0 ); densityHistogram->setColor ( "red" , 1 ); const Katabatic::GCellVector* gcells = getKiteEngine()->getGCellGrid()->getGCellVector(); getKiteEngine()->getGCellGrid()->setDensityMode ( Katabatic::GCellGrid::MaxHVDensity ); for ( size_t igcell=0 ; igcell<(*gcells).size() ; ++igcell ) { densityHistogram->addSample ( (*gcells)[igcell]->getDensity(), 0 ); } getKiteEngine()->getGCellGrid()->setDensityMode ( Katabatic::GCellGrid::MaxDensity ); for ( size_t igcell=0 ; igcell<(*gcells).size() ; ++igcell ) { densityHistogram->addSample ( (*gcells)[igcell]->getDensity(), 1 ); } densityHistogram->normalize ( 0 ); densityHistogram->normalize ( 1 ); } string NegociateWindow::_getString () const { ostringstream os; os << "<" << _getTypeName() << ">"; return ( os.str() ); } Record* NegociateWindow::_getRecord () const { Record* record = new Record ( _getString() ); record->add ( getSlot ( "_gcells", _gcells ) ); return ( record ); } } // End of Kite namespace.