// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | 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 : "./KatanaEngine.cpp" | // +-----------------------------------------------------------------+ #include #include #include #include #include "flute.h" #include "hurricane/utilities/Path.h" #include "hurricane/DebugSession.h" #include "hurricane/UpdateSession.h" #include "hurricane/Bug.h" #include "hurricane/Error.h" #include "hurricane/Warning.h" #include "hurricane/Breakpoint.h" #include "hurricane/Timer.h" #include "hurricane/Layer.h" #include "hurricane/Net.h" #include "hurricane/Pad.h" #include "hurricane/Plug.h" #include "hurricane/Cell.h" #include "hurricane/Instance.h" #include "hurricane/Vertical.h" #include "hurricane/Horizontal.h" #include "hurricane/RoutingPad.h" #include "hurricane/viewer/Script.h" #include "crlcore/Measures.h" #include "crlcore/AllianceFramework.h" #include "anabatic/AutoContact.h" #include "katana/Block.h" #include "katana/DataNegociate.h" #include "katana/RoutingPlane.h" #include "katana/Session.h" #include "katana/TrackSegment.h" #include "katana/NegociateWindow.h" #include "katana/KatanaEngine.h" #include "katana/PyKatanaEngine.h" namespace { using namespace std; using Hurricane::Error; using Hurricane::NetRoutingState; using Hurricane::NetRoutingExtension; using Hurricane::Net; using Hurricane::Cell; using Hurricane::Segment; using Hurricane::Plug; using Katana::Session; using Katana::TrackSegment; #if THIS_IS_DISABLED void setSymmetricSelf ( Cell* cell, string name ) { Net* net = cell->getNet( name ); if (not net) throw Error( "::setSymmetricSelf() Net \"%s\" not found." , name.c_str() ); NetRoutingState* state = NetRoutingExtension::get( net ); if (not state) state = NetRoutingExtension::create( net ); state->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | NetRoutingState::Vertical ); state->setSymAxis( cell->getAbutmentBox().getCenter().getX() ); } void setSymmetricPair ( Cell* cell, string masterName, string slaveName ) { Net* masterNet = cell->getNet( masterName ); if (not masterNet) throw Error( "::setSymmetricPair() Net \"%s\" not found." , masterName.c_str() ); NetRoutingState* masterState = NetRoutingExtension::get( masterNet ); if (not masterState) masterState = NetRoutingExtension::create( masterNet ); masterState->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | NetRoutingState::SymmetricMaster | NetRoutingState::Vertical ); masterState->setSymAxis( cell->getAbutmentBox().getCenter().getX() ); Net* slaveNet = cell->getNet( slaveName ); if (not slaveNet) throw Error( "KatanaEngine::runTest() Net \"%s\" not found." , slaveName.c_str() ); NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet ); if (not slaveState) slaveState = NetRoutingExtension::create( slaveNet ); slaveState ->setFlags ( NetRoutingState::AutomaticGlobalRoute | NetRoutingState::Symmetric | NetRoutingState::Vertical ); slaveState ->setSymAxis(cell->getAbutmentBox().getCenter().getX() ); slaveState ->setSymNet ( masterNet ); masterState->setSymNet ( slaveNet ); } #endif } // Anonymous namespace. namespace Katana { using std::cout; using std::cerr; using std::endl; using std::dec; using std::setw; using std::setfill; using std::left; using std::ostream; using std::ofstream; using std::ostringstream; using std::setprecision; using std::vector; using std::make_pair; using Hurricane::dbo_ptr; using Hurricane::UpdateSession; using Hurricane::DebugSession; using Hurricane::tab; using Hurricane::ForEachIterator; using Hurricane::Bug; using Hurricane::Error; using Hurricane::Warning; using Hurricane::Breakpoint; using Hurricane::Timer; using Hurricane::Box; using Hurricane::Torus; using Hurricane::Layer; using Hurricane::Entity; using Hurricane::Horizontal; using Hurricane::Vertical; using Hurricane::RoutingPad; using Hurricane::NetRoutingState; using Hurricane::NetRoutingExtension; using Hurricane::Cell; using Hurricane::Instance; using CRL::System; using CRL::Catalog; using CRL::AllianceFramework; using CRL::addMeasure; using CRL::Measures; using CRL::MeasuresSet; using Anabatic::Edge; using Anabatic::EngineState; using Anabatic::GCellsUnder; using Anabatic::AutoContact; using Anabatic::AutoSegmentLut; using Anabatic::ChipTools; const char* missingRW = "%s:\n\n" " Cell %s do not have any KatanaEngine (or not yet created).\n"; // ------------------------------------------------------------------- // Class : "Katana::KatanaEngine". Name KatanaEngine::_toolName = "Katana"; const Name& KatanaEngine::staticGetName () { return _toolName; } KatanaEngine* KatanaEngine::get ( const Cell* cell ) { return static_cast(ToolEngine::get(cell,staticGetName())); } KatanaEngine::KatanaEngine ( Cell* cell ) : Super (cell) , _viewer (NULL) , _blocks () , _routingPlanes () , _negociateWindow(NULL) , _minimumWL (0.0) , _shortDoglegs () , _symmetrics () , _stage (StageNegociate) , _successState (0) { } void KatanaEngine::_postCreate () { Super::_postCreate(); //Entity::setMemoryLimit( 1024 ); // 1Gb. addMeasure( "Gates" , AllianceFramework::getInstancesCount(getCell() ,AllianceFramework::IgnoreNonLogic |AllianceFramework::TerminalNetlist |AllianceFramework::Recursive) ); // Flute: load POWV9.dat & POST9.dat Flute::readLUT( System::getPath( "coriolis_top" ).toString() ); } Configuration* KatanaEngine::_createConfiguration () { return new Configuration(); } void KatanaEngine::_runKatanaInit () { Utilities::Path pythonSitePackages = System::getPath("pythonSitePackages"); Utilities::Path systemConfDir = pythonSitePackages / "katana"; Utilities::Path systemConfFile = systemConfDir / "katanaInit.py"; if (systemConfFile.exists()) { Isobar::Script::addPath( systemConfDir.toString() ); dbo_ptr script = Isobar::Script::create( systemConfFile.stem().toString() ); script->addKwArgument( "katana" , (PyObject*)PyKatanaEngine_Link(this) ); script->runFunction ( "katanaHook", getCell() ); Isobar::Script::removePath( systemConfDir.toString() ); } else { cerr << Warning( "Katana system configuration file:\n <%s> not found." , systemConfFile.toString().c_str() ) << endl; } } void KatanaEngine::digitalInit () { cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl; _runKatanaInit(); setRoutingMode( DigitalMode ); Super::chipPrep(); setupChannelMode(); setupGlobalGraph( 0 ); if (not isChannelStyle()) { setupRoutingPlanes(); } setupSpecialNets(); if (not setupPreRouteds()) { setState( Anabatic::EngineDriving ); throw Error( "KatanaEngine::digitalInit(): All nets are already routed, doing nothing." ); } else { if (not isChannelStyle()) { setupPowerRails(); Flags flags = (getConfiguration()->getNetBuilderStyle() == "VH,2RL") ? Flags::ProtectSelf : Flags::NoFlags; protectRoutingPads( flags ); } } cdebug_tabw(155,-1); } void KatanaEngine::analogInit () { cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl; resetRoutingMode( DigitalMode ); setRoutingMode( AnalogMode ); Super::chipPrep(); setupRoutingPlanes(); _runKatanaInit(); cdebug_tabw(155,-1); } void KatanaEngine::setupChannelMode () { cdebug_log(155,1) << "KatanaEngine::setupChannelMode()" << endl; RoutingGauge* rg = getConfiguration()->getRoutingGauge(); if (isChannelStyle()) { cmess1 << " - Running in channel mode." << endl; size_t maxDepth = rg->getDepth(); if (maxDepth < 2) { throw Error( "KatanaEngine::setupChannelMode(): Layer gauge %s must contains at least two layers (%u)." , getString(rg->getName()).c_str(), maxDepth ); } } cdebug_tabw(155,-1); } void KatanaEngine::setupRoutingPlanes () { cdebug_log(155,1) << "KatanaEngine::setupRoutingPlanes()" << endl; bool sessionReUse = Session::isOpen(); if (not sessionReUse) openSession(); size_t maxDepth = getConfiguration()->getRoutingGauge()->getDepth(); _routingPlanes.reserve( maxDepth ); for ( size_t depth=0 ; depth < maxDepth ; depth++ ) { _routingPlanes.push_back( RoutingPlane::create( this, depth ) ); cdebug_log(155,0) << _routingPlanes.back() << endl; } if (not sessionReUse) Session::close(); cdebug_tabw(155,-1); } KatanaEngine* KatanaEngine::create ( Cell* cell ) { AllianceFramework* af = AllianceFramework::get(); for ( Instance* instance : cell->getInstances() ) { if (af->isPad(instance->getMasterCell())) { throw Error( "KatanaEngine::create(): Must not be run at chip level, but a corona level.\n" " Guessing \"%s\" is a chip because instance \"%s\" is a pad (\"%s\")." , getString(cell->getName()).c_str() , getString(instance->getName()).c_str() , getString(instance->getMasterCell()->getName()).c_str() ); } } KatanaEngine* katana = new KatanaEngine ( cell ); katana->_postCreate(); return katana; } void KatanaEngine::_preDestroy () { cdebug_log(155,1) << "KatanaEngine::_preDestroy()" << endl; cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <" << _cell->getName() << ">" << endl; if (getState() < EngineState::EngineGutted) setState( EngineState::EnginePreDestroying ); _gutKatana(); Super::_preDestroy(); cmess2 << " - RoutingEvents := " << RoutingEvent::getAllocateds() << endl; cdebug_tabw(155,-1); } KatanaEngine::~KatanaEngine () { } const Name& KatanaEngine::getName () const { return _toolName; } Configuration* KatanaEngine::getConfiguration () { return static_cast( Super::getConfiguration() ); } const Configuration* KatanaEngine::getConfiguration () const { return static_cast( Super::getConfiguration() ); } uint32_t KatanaEngine::getRipupLimit ( const TrackElement* segment ) const { if (segment->isBlockage()) return 0; if (segment->isStrap ()) return getConfiguration()->getRipupLimit( Configuration::StrapRipupLimit ); if (segment->isUnbreakable()) return getConfiguration()->getRipupLimit( Configuration::StrapRipupLimit ); if (segment->isShortNet ()) return getConfiguration()->getRipupLimit( Configuration::ShortNetRipupLimit ); if (segment->isGlobal ()) { vector gcells; segment->getGCells( gcells ); if (gcells.size() > 2) return getConfiguration()->getRipupLimit( Configuration::LongGlobalRipupLimit ); return getConfiguration()->getRipupLimit( Configuration::GlobalRipupLimit ); } return getConfiguration()->getRipupLimit( Configuration::LocalRipupLimit ); } RoutingPlane* KatanaEngine::getRoutingPlaneByIndex ( size_t index ) const { if (index >= getRoutingPlanesSize() ) return NULL; return _routingPlanes[index]; } RoutingPlane* KatanaEngine::getRoutingPlaneByLayer ( const Layer* layer ) const { for ( size_t index=0 ; index < getRoutingPlanesSize() ; index++ ) { if (_routingPlanes[index]->getLayer() == layer) return _routingPlanes[index]; } return NULL; } Track* KatanaEngine::getTrackByPosition ( const Layer* layer, DbU::Unit axis, uint32_t mode ) const { RoutingPlane* plane = getRoutingPlaneByLayer( layer ); if (not plane) return NULL; return plane->getTrackByPosition( axis, mode ); } DataSymmetric* KatanaEngine::getDataSymmetric ( Net* net ) { auto idata = _symmetrics.find( net ); if (idata != _symmetrics.end()) return (*idata).second; return NULL; } void KatanaEngine::openSession () { Session::_open(this); } void KatanaEngine::setInterrupt ( bool state ) { if (_negociateWindow) { _negociateWindow->setInterrupt( state ); cerr << "Interrupt [CRTL+C] of " << this << endl; } } DataSymmetric* KatanaEngine::addDataSymmetric ( Net* net ) { DataSymmetric* data = getDataSymmetric( net ); if (data) { cerr << Error( "KatanaEngine::addDataSymmetric(): Try to add twice Net \"%s\" (ignored)." , getString(net->getName()).c_str() ) << endl; return data; } data = DataSymmetric::create( net ); if (data) { _symmetrics.insert( make_pair(net,data) ); if (data->getSymNet()) _symmetrics.insert( make_pair(data->getSymNet(),data) ); } return data; } void KatanaEngine::annotateGlobalGraph () { cmess1 << " o Back annotate global routing graph." << endl; for ( size_t depth=0 ; depth<_routingPlanes.size() ; ++depth ) { RoutingPlane* rp = _routingPlanes[depth]; if (rp->getLayerGauge()->getType() == Constant::PinOnly) continue; if (rp->getLayerGauge()->getDepth() > getConfiguration()->getAllowedDepth()) continue; int elementCapacity = 1; size_t tracksSize = rp->getTracksSize(); for ( size_t itrack=0 ; itrackgetTrackByIndex( itrack ); DbU::Unit axis = track->getAxis(); Flags side = (track->getDirection() == Flags::Vertical) ? Flags::NorthSide : Flags::EastSide; Point source; Point target; cdebug_log(159,0) << "Capacity from: " << track << endl; Interval uspan; for ( size_t ielement=0 ; ielementgetSize() ; ++ielement ) { TrackElement* element = track->getSegment( ielement ); if (element->getNet() == NULL) { cdebug_log(159,0) << "Reject capacity from (not Net): " << element << endl; continue; } if ( (not element->isFixed()) and (not element->isBlockage()) and (not element->isUserDefined()) ) { cmess2 << "Reject capacity from (neither fixed, blockage nor user defined): " << element << endl; continue; } cdebug_log(159,0) << "Capacity from: " << element << ":" << elementCapacity << endl; Segment* segment = element->getSegment(); Interval segmentUSpan; source = segment->getSourcePosition(); target = segment->getTargetPosition(); if (track->getDirection() == Flags::Vertical) segmentUSpan = Interval( source.getY(), target.getY() ); else segmentUSpan = Interval( source.getX(), target.getX() ); if (uspan.isEmpty()) { uspan = segmentUSpan; continue; } else { if (uspan.contains(segmentUSpan)) continue; if (uspan.intersect(segmentUSpan)) { uspan.merge( segmentUSpan ); continue; } } if (track->getDirection() == Flags::Vertical) { source = Point( axis, uspan.getVMin() ); target = Point( axis, uspan.getVMax() ); } else { source = Point( uspan.getVMin(), axis ); target = Point( uspan.getVMax(), axis ); } GCellsUnder gcells = getGCellsUnder( source, target ); if (not gcells->empty()) { for ( size_t i=0 ; isize()-1 ; ++i ) { Edge* edge = gcells->gcellAt(i)->getEdgeAt( side, axis ); edge->reserveCapacity( elementCapacity ); } } uspan = segmentUSpan; } if (not uspan.isEmpty()) { if (track->getDirection() == Flags::Vertical) { source = Point( axis, uspan.getVMin() ); target = Point( axis, uspan.getVMax() ); } else { source = Point( uspan.getVMin(), axis ); target = Point( uspan.getVMax(), axis ); } GCellsUnder gcells = getGCellsUnder( source, target ); if (not gcells->empty()) { for ( size_t i=0 ; isize()-1 ; ++i ) { Edge* edge = gcells->gcellAt(i)->getEdgeAt( side, axis ); edge->reserveCapacity( elementCapacity ); } } } } } if (Session::isChannelStyle()) { for ( GCell* gcell : getGCells() ) { if (not gcell->isStdCellRow()) continue; set terminalsX; for ( Component* component : getCell()->getComponentsUnder(gcell->getBoundingBox()) ) { RoutingPad* rp = dynamic_cast( component ); if (rp) terminalsX.insert( rp->getX() ); } unsigned int capacity = 0; Edge* edge = gcell->getNorthEdge(); if (edge) { capacity = edge->getCapacity(); if (terminalsX.size() < capacity) capacity = terminalsX.size(); edge->reserveCapacity( capacity ); } edge = gcell->getSouthEdge(); if (edge) { capacity = edge->getCapacity(); if (terminalsX.size()/2 < capacity) capacity = terminalsX.size()/2; edge->reserveCapacity( capacity ); } } } else { uint32_t hReservedMin = getConfiguration()->getHTracksReservedMin(); uint32_t vReservedMin = getConfiguration()->getVTracksReservedMin(); for ( GCell* gcell : getGCells() ) { if (not gcell->isMatrix()) continue; for ( Edge* edge : gcell->getEdges( Flags::NorthSide) ) { if (edge->getReservedCapacity() < vReservedMin) { edge->reserveCapacity( vReservedMin - edge->getReservedCapacity() ); } } for ( Edge* edge : gcell->getEdges( Flags::EastSide) ) { if (edge->getReservedCapacity() < hReservedMin) edge->reserveCapacity( hReservedMin - edge->getReservedCapacity() ); } gcell->postGlobalAnnotate(); } } } void KatanaEngine::runNegociate ( Flags flags ) { if (_negociateWindow) return; addMeasure( "GCells", getGCells().size() ); startMeasures(); openSession(); _negociateWindow = NegociateWindow::create( this ); _negociateWindow->setGCells( getGCells() ); _negociateWindow->run( flags ); _negociateWindow->destroy(); _negociateWindow = NULL; getCell()->setTerminalNetlist( true ); Session::close(); stopMeasures(); //if ( _editor ) _editor->refresh (); printMeasures( "algo" ); openSession(); uint32_t overlaps = 0; // size_t hTracksReservedLocal = getHTracksReservedLocal(); // size_t vTracksReservedLocal = getVTracksReservedLocal(); // if (cparanoid.enabled()) { // cparanoid << " o Post-checking Katana capacity overload h:" << hTracksReservedLocal // << " v:." << vTracksReservedLocal << endl; // getGCellGrid()->checkEdgeOverflow( hTracksReservedLocal, vTracksReservedLocal ); // } _check( overlaps ); Session::close(); setDetailedRoutingSuccess( isDetailedRoutingSuccess() and (overlaps == 0) ); } void KatanaEngine::runTest () { #if PUT_HERE_WHATEVER_YOU_WANT_TO_TEST if (getCell()->getName() != "gmchamla") throw Error( "KatanaEngine::runTest() Work only on \"gmchamla\" (loaded:\"%s\")." , getString(getCell()->getName()).c_str() ); setSymmetricSelf( getCell(), "Vc" ); setSymmetricSelf( getCell(), "vb5" ); setSymmetricSelf( getCell(), "vb7" ); setSymmetricPair( getCell(), "ampp_73", "ampn_72" ); setSymmetricPair( getCell(), "ampp_71", "ampn_71" ); setSymmetricPair( getCell(), "m2n_in" , "m2p_in" ); setSymmetricPair( getCell(), "ampp_4" , "ampn_4" ); setSymmetricPair( getCell(), "ampp_2" , "ampn_2" ); setSymmetricPair( getCell(), "ampp_1" , "ampn_1" ); #endif } void KatanaEngine::printCompletion () const { size_t routeds = 0; uint64_t totalWireLength = 0; uint64_t routedWireLength = 0; uint32_t hunrouteds = 0; uint32_t vunrouteds = 0; vector unrouteds; vector reduceds; ostringstream result; bool isSymbolic = const_cast(this)->getConfiguration()->getRoutingGauge()->isSymbolic(); // Max symbolic wire: 100000L, max real wire: 5mm. uint64_t maxWL = (isSymbolic) ? DbU::fromLambda( 100000.0 ) : DbU::fromPhysical( 5.0, DbU::UnitPower::Milli ); AutoSegmentLut::const_iterator ilut = _getAutoSegmentLut().begin(); for ( ; ilut != _getAutoSegmentLut().end() ; ilut++ ) { TrackElement* segment = _lookup( ilut->second ); if (segment == NULL) continue; uint64_t wl = 0; if (isSymbolic) wl = (uint64_t)DbU::toLambda( segment->getLength() ); else wl = (uint64_t)DbU::toPhysical( segment->getLength(), DbU::UnitPower::Nano ); if (wl > maxWL) { cerr << Error("KatanaEngine::printCompletion(): Suspiciously long wire: %llu for %p:%s" ,wl,ilut->first,getString(segment).c_str()) << endl; continue; } if (segment->isFixed() or segment->isBlockage()) continue; if (segment->isReduced()) reduceds.push_back( segment ); totalWireLength += wl; if ( (segment->getTrack() != NULL) or (segment->isReduced()) ) { routeds++; routedWireLength += wl; continue; } unrouteds.push_back( segment ); if (segment->isHorizontal()) ++hunrouteds; if (segment->isVertical ()) ++vunrouteds; } float segmentRatio = (float)(routeds) / (float)(routeds+unrouteds.size()) * 100.0; float wireLengthRatio = (float)(routedWireLength) / (float)(totalWireLength) * 100.0; setDetailedRoutingSuccess( unrouteds.empty() ); if (not unrouteds.empty()) { cerr << " o Routing did not complete, unrouted segments:" << endl; for ( size_t i=0; i ( "Segs" , routeds+unrouteds.size() ); addMeasure( "DWL" , totalWireLength , 12 ); addMeasure( "fWL" , totalWireLength-routedWireLength , 12 ); addMeasure ( "WLER(%)", expandRatio ); } void KatanaEngine::dumpMeasures ( ostream& out ) const { vector measuresLabels; measuresLabels.push_back( getMeasureLabel("Gates" ) ); measuresLabels.push_back( getMeasureLabel("GCells" ) ); //measuresLabels.push_back( getMeasureLabel("knikT" ) ); //measuresLabels.push_back( getMeasureLabel("knikS" ) ); //measuresLabels.push_back( getMeasureLabel("GWL" ) ); measuresLabels.push_back( "Etesian::EtesianEngine.placeT" ); measuresLabels.push_back( getMeasureLabel("Area" ) ); measuresLabels.push_back( getMeasureLabel("Sat" ) ); measuresLabels.push_back( getMeasureLabel("loadT" ) ); measuresLabels.push_back( getMeasureLabel("loadS" ) ); measuresLabels.push_back( getMeasureLabel("H-ovE" ) ); measuresLabels.push_back( getMeasureLabel("V-ovE" ) ); measuresLabels.push_back( getMeasureLabel("Globals") ); measuresLabels.push_back( getMeasureLabel("Edges" ) ); measuresLabels.push_back( getMeasureLabel("assignT") ); measuresLabels.push_back( getMeasureLabel("algoT" ) ); measuresLabels.push_back( getMeasureLabel("algoS" ) ); measuresLabels.push_back( getMeasureLabel("finT" ) ); measuresLabels.push_back( getMeasureLabel("Segs" ) ); measuresLabels.push_back( getMeasureLabel("DWL" ) ); measuresLabels.push_back( getMeasureLabel("fWL" ) ); measuresLabels.push_back( getMeasureLabel("WLER(%)") ); measuresLabels.push_back( getMeasureLabel("Events" ) ); measuresLabels.push_back( getMeasureLabel("UEvents") ); const MeasuresSet* measures = Measures::get( getCell() ); if (measures) { out << "#" << endl; out << "# " << getCell()->getName() << endl; out << measures->toStringHeaders(measuresLabels) << endl; for ( size_t i=0 ; i<=getPassNumber() ; ++i ) { out << measures->toStringDatas(measuresLabels,i) << endl; measures->toGnuplot( getMeasureLabel("GCells Density Histogram") , i, getString(getCell()->getName()) ); } } else { cerr << Warning( "KatanaEngine::dumpMeasures(): \"%s\" has no measures yet." , getString(getCell()->getName()).c_str() ) << endl; } } void KatanaEngine::dumpMeasures () const { cmess1 << " o Dumping measurements." << endl; ostringstream path; path << getCell()->getName() << ".katana.dat"; ofstream sfile ( path.str().c_str() ); dumpMeasures( sfile ); sfile.close(); } bool KatanaEngine::_check ( uint32_t& overlap, const char* message ) const { cmess1 << " o Checking Katana Database coherency." << endl; bool coherency = true; coherency = coherency and Super::_check( message ); for ( size_t i=0 ; i<_routingPlanes.size() ; i++ ) coherency = _routingPlanes[i]->_check(overlap) and coherency; Anabatic::Session* anbtSession = Session::base (); for( Net* net : getCell()->getNets() ) { for( Segment* segment : net->getComponents().getSubSet() ) { AutoSegment* autoSegment = anbtSession->lookup( segment ); if (not autoSegment) continue; if (not autoSegment->isCanonical()) continue; if (autoSegment->isReduced()) continue; TrackElement* trackSegment = Session::lookup( segment ); if (not trackSegment) { if ( isChannelStyle() and autoSegment->isFixed() and autoSegment->isHorizontal() and autoSegment->isNonPref()) continue; coherency = false; cerr << Bug( "%p %s without Track Segment" , autoSegment , getString(autoSegment).c_str() ) << endl; } else trackSegment->_check(); } } return coherency; } void KatanaEngine::finalizeLayout () { cdebug_log(155,0) << "KatanaEngine::finalizeLayout()" << endl; if (getState() > Anabatic::EngineDriving) return; cdebug_tabw(155,1); setState( Anabatic::EngineDriving ); _gutKatana(); Super::finalizeLayout(); cdebug_log(155,0) << "State: " << getState() << endl; getCell()->setFlags( Cell::Flags::Routed ); cdebug_tabw(155,-1); } void KatanaEngine::_gutKatana () { cdebug_log(155,1) << "KatanaEngine::_gutKatana()" << endl; cdebug_log(155,0) << "State: " << getState() << endl; if (getState() < EngineState::EngineGutted) { openSession(); for ( Block* block : _blocks ) delete block; _blocks.clear(); size_t maxDepth = std::min( getConfiguration()->getRoutingGauge()->getDepth(), _routingPlanes.size() ); for ( size_t depth=0 ; depth < maxDepth ; depth++ ) { _routingPlanes[depth]->destroy(); } _routingPlanes.clear(); while ( not _symmetrics.empty() ) { auto element = _symmetrics.begin(); if (element->first == element->second->getNet()) delete element->second; _symmetrics.erase( element->first ); } Session::close(); } cdebug_tabw(155,-1); } void KatanaEngine::resetRouting () { _gutKatana(); UpdateSession::open(); for ( Net* net : getCell()->getNets() ) { vector removeds; for ( Component* component : net->getComponents() ) { if (dynamic_cast(component)) continue; if (dynamic_cast(component)) removeds.push_back( component ); } for ( Component* component : removeds ) component->destroy(); } for ( Net* net : getCell()->getNets() ) { vector removeds; for ( Component* component : net->getComponents() ) { if (dynamic_cast(component)) continue; removeds.push_back( component ); } for ( Component* component : removeds ) component->destroy(); } setState( Anabatic::EngineCreation ); setGlobalRoutingSuccess ( false ); setDetailedRoutingSuccess( false ); UpdateSession::close(); getCell()->resetFlags( Cell::Flags::Routed ); } TrackElement* KatanaEngine::_lookup ( Segment* segment ) const { AutoSegment* autoSegment = Super::_lookup( segment ); if (not autoSegment or not autoSegment->isCanonical()) return NULL; return _lookup( autoSegment ); } void KatanaEngine::_check ( Net* net ) const { cerr << " o Checking " << net << endl; for( Segment* segment : net->getComponents().getSubSet() ) { TrackElement* trackSegment = _lookup( segment ); if (trackSegment) { trackSegment->_check(); AutoContact* autoContact = trackSegment->base()->getAutoSource(); if (autoContact) autoContact->checkTopology (); autoContact = trackSegment->base()->getAutoTarget(); if (autoContact) autoContact->checkTopology (); } } } string KatanaEngine::_getTypeName () const { return "Katana::KatanaEngine"; } string KatanaEngine::_getString () const { ostringstream os; os << "<" << "KatanaEngine " << _cell->getName () << ">"; return os.str(); } Record* KatanaEngine::_getRecord () const { Record* record = Super::_getRecord (); if (record) { record->add( getSlot( "_blocks" , &_blocks ) ); record->add( getSlot( "_routingPlanes", &_routingPlanes ) ); record->add( getSlot( "_symmetrics" , &_symmetrics ) ); } return record; } } // Katana namespace.