coriolis/kite/src/KiteEngine.cpp

902 lines
29 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, 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 : "./KiteEngine.cpp" |
// +-----------------------------------------------------------------+
#include <Python.h>
#include <sstream>
#include <fstream>
#include <iomanip>
#include "vlsisapd/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/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/viewer/Script.h"
#include "crlcore/Measures.h"
#include "knik/Vertex.h"
#include "knik/Edge.h"
#include "knik/Graph.h"
#include "knik/KnikEngine.h"
#include "katabatic/AutoContact.h"
#include "katabatic/GCellGrid.h"
#include "kite/DataNegociate.h"
#include "kite/RoutingPlane.h"
#include "kite/Session.h"
#include "kite/TrackSegment.h"
#include "kite/NegociateWindow.h"
#include "kite/KiteEngine.h"
#include "kite/PyKiteEngine.h"
namespace Kite {
using std::cout;
using std::cerr;
using std::endl;
using std::dec;
using std::setw;
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::Box;
using Hurricane::Torus;
using Hurricane::Layer;
using Hurricane::Horizontal;
using Hurricane::Vertical;
using Hurricane::NetRoutingExtension;
using Hurricane::Cell;
using CRL::System;
using CRL::addMeasure;
using CRL::Measures;
using CRL::MeasuresSet;
using Knik::KnikEngine;
using Katabatic::AutoContact;
using Katabatic::AutoSegmentLut;
using Katabatic::ChipTools;
const char* missingRW =
"%s :\n\n"
" Cell %s do not have any KiteEngine (or not yet created).\n";
// -------------------------------------------------------------------
// Class : "Kite::KiteEngine".
Name KiteEngine::_toolName = "Kite";
const Name& KiteEngine::staticGetName ()
{ return _toolName; }
KiteEngine* KiteEngine::get ( const Cell* cell )
{ return static_cast<KiteEngine*>(ToolEngine::get(cell,staticGetName())); }
KiteEngine::KiteEngine ( Cell* cell )
: KatabaticEngine (cell)
, _viewer (NULL)
, _knik (NULL)
, _blockageNet (cell->getNet("blockagenet"))
, _configuration (new Configuration(getKatabaticConfiguration()))
, _routingPlanes ()
, _negociateWindow (NULL)
, _minimumWL (0.0)
, _toolSuccess (false)
{ }
void KiteEngine::_postCreate ()
{
KatabaticEngine::_postCreate ();
}
void KiteEngine::_runKiteInit ()
{
Utilities::Path pythonSitePackages = System::getPath("pythonSitePackages");
Utilities::Path systemConfDir = pythonSitePackages / "kite";
Utilities::Path systemConfFile = systemConfDir / "kiteInit.py";
if (systemConfFile.exists()) {
Isobar::Script::addPath( systemConfDir.toString() );
dbo_ptr<Isobar::Script> script = Isobar::Script::create( systemConfFile.stem().toString() );
script->addKwArgument( "kite" , (PyObject*)PyKiteEngine_Link(this) );
script->runFunction ( "kiteHook", getCell() );
Isobar::Script::removePath( systemConfDir.toString() );
} else {
cerr << Warning("Kite system configuration file:\n <%s> not found."
,systemConfFile.toString().c_str()) << endl;
}
}
void KiteEngine::_initDataBase ()
{
cdebug_log(155,1) << "KiteEngine::_initDataBase()" << endl;
Session::open( this );
createGlobalGraph( KtNoFlags );
createDetailedGrid();
findSpecialNets();
buildPreRouteds();
buildPowerRails();
protectRoutingPads();
Session::close();
_runKiteInit();
cdebug_tabw(155,-1);
}
KiteEngine* KiteEngine::create ( Cell* cell )
{
KiteEngine* kite = new KiteEngine ( cell );
kite->_postCreate();
kite->_initDataBase();
return kite;
}
void KiteEngine::_preDestroy ()
{
cdebug_log(155,1) << "KiteEngine::_preDestroy()" << endl;
cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <"
<< _cell->getName() << ">" << endl;
if (getState() < Katabatic::EngineGutted)
setState( Katabatic::EnginePreDestroying );
_gutKite();
KatabaticEngine::_preDestroy();
cmess2 << " - RoutingEvents := " << RoutingEvent::getAllocateds() << endl;
if (not ToolEngine::inDestroyAll()) {
KnikEngine* attachedKnik = KnikEngine::get( getCell() );
if (_knik != attachedKnik) {
cerr << Error("Knik attribute differs from the Cell attached one (must be the same)\n"
" On: <%s>."
,getString(getCell()->getName()).c_str()) << endl;
_knik = attachedKnik;
}
_knik->destroy();
}
cdebug_tabw(155,-1);
}
void KiteEngine::wipeoutRouting ( Cell * cell )
{
if ( (KiteEngine::get(cell) != NULL) or (KatabaticEngine::get(cell) != NULL) )
throw Error( "KiteEngine::wipeoutRouting(): KiteEngine still active on %s"
, getString(cell->getName()).c_str() );
UpdateSession::open();
for ( Net* net : cell->getNets() ) {
if (NetRoutingExtension::isManualGlobalRoute(net)) continue;
// First pass: destroy the contacts
std::vector<Contact*> contacts;
for ( Component* component : net->getComponents() ) {
Contact* contact = dynamic_cast<Contact*>(component);
if (contact and not contact->getAnchorHook()->isAttached())
contacts.push_back( contact );
}
for ( Contact* contact : contacts )
contact->destroy();
// Second pass: destroy unconnected segments added by Knik as blockages
std::vector<Component*> segments;
for ( Component* component : net->getComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) segments.push_back( horizontal );
Vertical* vertical = dynamic_cast<Vertical*>(component);
if (vertical) segments.push_back( vertical );
}
for ( Component* segment : segments )
segment->destroy();
}
UpdateSession::close();
}
KiteEngine::~KiteEngine ()
{ delete _configuration; }
const Name& KiteEngine::getName () const
{ return _toolName; }
Configuration* KiteEngine::getConfiguration ()
{ return _configuration; }
unsigned int KiteEngine::getRipupLimit ( const TrackElement* segment ) const
{
if (segment->isBlockage()) return 0;
if (segment->isStrap ()) return _configuration->getRipupLimit( Configuration::StrapRipupLimit );
if (segment->isGlobal()) {
Katabatic::GCellVector gcells;
segment->getGCells( gcells );
if (gcells.size() > 2)
return _configuration->getRipupLimit( Configuration::LongGlobalRipupLimit );
return _configuration->getRipupLimit( Configuration::GlobalRipupLimit );
}
return _configuration->getRipupLimit( Configuration::LocalRipupLimit );
}
RoutingPlane* KiteEngine::getRoutingPlaneByIndex ( size_t index ) const
{
if (index >= getRoutingPlanesSize() ) return NULL;
return _routingPlanes[index];
}
RoutingPlane* KiteEngine::getRoutingPlaneByLayer ( const Layer* layer ) const
{
for ( size_t index=0 ; index < getRoutingPlanesSize() ; index++ ) {
if (_routingPlanes[index]->getLayer() == layer)
return _routingPlanes[index];
}
return NULL;
}
Track* KiteEngine::getTrackByPosition ( const Layer* layer, DbU::Unit axis, unsigned int mode ) const
{
RoutingPlane* plane = getRoutingPlaneByLayer( layer );
if (not plane) return NULL;
return plane->getTrackByPosition( axis, mode );
}
void KiteEngine::setInterrupt ( bool state )
{
if (_negociateWindow) {
_negociateWindow->setInterrupt( state );
cerr << "Interrupt [CRTL+C] of " << this << endl;
}
}
void KiteEngine::createGlobalGraph ( unsigned int mode )
{
Cell* cell = getCell();
//Box cellBb = cell->getBoundingBox();
if (not _knik) {
unsigned int flags = Cell::Flags::WarnOnUnplacedInstances;
flags |= (mode & KtBuildGlobalRouting) ? Cell::Flags::BuildRings : 0;
cell->flattenNets( flags );
cell->createRoutingPadRings( Cell::Flags::BuildRings );
KatabaticEngine::chipPrep();
KnikEngine::setHEdgeReservedLocal( 0 );
KnikEngine::setVEdgeReservedLocal( 0 );
_knik = KnikEngine::create( cell
, 1 // _congestion
, 2 // _preCongestion
, false // _benchMode
, true // _useSegments
, 2.5 // _edgeCost
);
_knik->setRoutingGauge( getConfiguration()->getRoutingGauge() );
_knik->setAllowedDepth( getConfiguration()->getAllowedDepth() );
_knik->createRoutingGraph();
KnikEngine::setHEdgeReservedLocal( getHTracksReservedLocal() );
KnikEngine::setVEdgeReservedLocal( getVTracksReservedLocal() );
// Decrease the edge's capacity only under the core area.
const ChipTools& chipTools = getChipTools();
size_t coreReserved = 0;
size_t coronaReserved = 4;
for( Knik::Vertex* vertex : _knik->getRoutingGraph()->getVertexes() ) {
if ( chipTools.isChip()
and ( chipTools.hPadsEnclosed(Box(vertex->getPosition()))
or chipTools.vPadsEnclosed(Box(vertex->getPosition()))) )
vertex->setBlocked();
for ( int i=0 ; i<2 ; ++i ) {
Knik::Edge* edge = NULL;
if (i==0) {
edge = vertex->getHEdgeOut();
if (not edge) continue;
if (chipTools.hPadsEnclosed(edge->getBoundingBox())) {
edge->setCapacity( 0 );
continue;
}
coreReserved = getHTracksReservedLocal();
} else {
edge = vertex->getVEdgeOut();
if (not edge) continue;
if (chipTools.vPadsEnclosed(edge->getBoundingBox())) {
edge->setCapacity( 0 );
continue;
}
coreReserved = getVTracksReservedLocal();
}
size_t edgeReserved = 0;
if (chipTools.getCorona().getInnerBox().contains(edge->getBoundingBox())) {
edgeReserved = coreReserved;
} else if (chipTools.getCorona().getOuterBox().contains(edge->getBoundingBox())) {
edgeReserved = coronaReserved;
}
size_t capacity = (edge->getCapacity()>edgeReserved)
? (edge->getCapacity()-edgeReserved) : 0;
//cerr << "Setting capacity " << capacity << " ("
// << capacity << ") on: " << edge << endl;
edge->setCapacity( capacity );
}
}
}
}
void KiteEngine::createDetailedGrid ()
{
KatabaticEngine::createDetailedGrid();
size_t maxDepth = getRoutingGauge()->getDepth();
_routingPlanes.reserve( maxDepth );
for ( size_t depth=0 ; depth < maxDepth ; depth++ ) {
_routingPlanes.push_back( RoutingPlane::create ( this, depth ) );
}
}
void KiteEngine::saveGlobalSolution ()
{
if (getState() < Katabatic::EngineGlobalLoaded)
throw Error ("KiteEngine::saveGlobalSolution(): Global routing not present yet.");
if (getState() > Katabatic::EngineGlobalLoaded)
throw Error ("KiteEngine::saveGlobalSolution(): Cannot save after detailed routing.");
_knik->saveSolution();
}
void KiteEngine::annotateGlobalGraph ()
{
cmess1 << " o Back annotate global routing graph." << endl;
//const Torus& chipCorona = getChipTools().getCorona();
int hEdgeCapacity = 0;
int vEdgeCapacity = 0;
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;
if (rp->getDirection() == KbHorizontal) ++hEdgeCapacity;
else ++vEdgeCapacity;
}
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;
size_t tracksSize = rp->getTracksSize();
for ( size_t itrack=0 ; itrack<tracksSize ; ++itrack ) {
Track* track = rp->getTrackByIndex ( itrack );
cdebug_log(159,0) << "Capacity from: " << track << endl;
if (track->getDirection() == KbHorizontal) {
for ( size_t ielement=0 ; ielement<track->getSize() ; ++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;
//cdebug_log(159,0) << "Reject capacity from (neither fixed nor blockage): " << element << endl;
continue;
}
//Box elementBb = element->getBoundingBox();
//int elementCapacity = (chipCorona.contains(elementBb)) ? -hEdgeCapacity : -1;
int elementCapacity = -1;
cdebug_log(159,0) << "Capacity from: " << element << ":" << elementCapacity << endl;
Katabatic::GCell* gcell = getGCellGrid()->getGCell( Point(element->getSourceU(),track->getAxis()) );
Katabatic::GCell* end = getGCellGrid()->getGCell( Point(element->getTargetU(),track->getAxis()) );
Katabatic::GCell* right = NULL;
if (not gcell) {
cerr << Warning("annotageGlobalGraph(): TrackElement outside GCell grid.") << endl;
continue;
}
while ( gcell and (gcell != end) ) {
right = gcell->getRight();
if (right == NULL) break;
_knik->increaseEdgeCapacity( gcell->getColumn()
, gcell->getRow()
, right->getColumn()
, right->getRow()
, elementCapacity );
gcell = right;
}
}
} else {
for ( size_t ielement=0 ; ielement<track->getSize() ; ++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()) ) {
cdebug_log(159,0) << "Reject capacity from (neither fixed nor blockage): " << element << endl;
continue;
}
//Box elementBb = element->getBoundingBox();
//int elementCapacity = (chipCorona.contains(elementBb)) ? -vEdgeCapacity : -1;
int elementCapacity = -1;
cdebug_log(159,0) << "Capacity from: " << element << ":" << elementCapacity << endl;
Katabatic::GCell* gcell = getGCellGrid()->getGCell( Point(track->getAxis(),element->getSourceU()) );
Katabatic::GCell* end = getGCellGrid()->getGCell( Point(track->getAxis(),element->getTargetU()) );
Katabatic::GCell* up = NULL;
if (not gcell) {
cerr << Warning("annotageGlobalGraph(): TrackElement outside GCell grid.") << endl;
continue;
}
while ( gcell and (gcell != end) ) {
up = gcell->getUp();
if (up == NULL) break;
_knik->increaseEdgeCapacity( gcell->getColumn()
, gcell->getRow()
, up->getColumn()
, up->getRow()
, elementCapacity );
gcell = up;
}
}
}
}
}
#if DISABLED
const Box& coreBox = chipCorona.getInnerBox();
Katabatic::GCell* gcell = NULL;
Katabatic::GCell* end = NULL;
Katabatic::GCell* hneighbor = NULL;
for ( size_t i=0 ; i<6 ; ++i ) {
switch ( i ) {
case 0:
case 1:
case 2:
gcell = getGCellGrid()->getGCell( Point(coreBox.getXMin(),coreBox.getYMin()) );
end = getGCellGrid()->getGCell( Point(coreBox.getXMin(),coreBox.getYMax()) );
break;
case 3:
case 4:
case 5:
gcell = getGCellGrid()->getGCell( Point(coreBox.getXMax(),coreBox.getYMin()) );
end = getGCellGrid()->getGCell( Point(coreBox.getXMax(),coreBox.getYMax()) );
break;
}
if (i % 3 == 0) {
gcell = gcell->getLeft();
end = end ->getLeft();
} else if (i % 3 == 2) {
gcell = gcell->getRight();
end = end ->getRight();
}
while ( gcell and (gcell != end) ) {
hneighbor = (i<3) ? gcell->getLeft() : gcell->getRight();
if (hneighbor == NULL) break;
_knik->updateEdgeCapacity( gcell->getColumn()
, gcell->getRow()
, hneighbor->getColumn()
, hneighbor->getRow()
, 3 );
cerr << "Decrease capacity of " << gcell << " (side) by " << hEdgeCapacity << "/2" << endl;
gcell = gcell->getUp();
}
}
#endif
}
void KiteEngine::runGlobalRouter ( unsigned int mode )
{
if (getState() >= Katabatic::EngineGlobalLoaded)
throw Error ("KiteEngine::runGlobalRouter(): Global routing already done or loaded.");
Session::open( this );
if (mode & KtLoadGlobalRouting) {
_knik->loadSolution();
} else {
annotateGlobalGraph();
map<Name,Net*> preRouteds;
for ( auto istate : getNetRoutingStates() ) {
if (istate.second->isMixedPreRoute())
preRouteds.insert( make_pair(istate.first, istate.second->getNet()) );
}
_knik->run( preRouteds );
}
setState( Katabatic::EngineGlobalLoaded );
Session::close();
}
void KiteEngine::loadGlobalRouting ( unsigned int method )
{
KatabaticEngine::loadGlobalRouting( method );
Session::open( this );
getGCellGrid()->checkEdgeOverflow( getHTracksReservedLocal(), getVTracksReservedLocal() );
Session::close();
}
void KiteEngine::runNegociate ( unsigned int flags )
{
if (_negociateWindow) return;
startMeasures();
Session::open( this );
_negociateWindow = NegociateWindow::create( this );
_negociateWindow->setGCells( *(getGCellGrid()->getGCellVector()) );
_computeCagedConstraints();
_negociateWindow->run( flags );
_negociateWindow->destroy();
_negociateWindow = NULL;
Session::close();
stopMeasures();
//if ( _editor ) _editor->refresh ();
printMeasures( "algo" );
Session::open( this );
unsigned int overlaps = 0;
size_t hTracksReservedLocal = getHTracksReservedLocal();
size_t vTracksReservedLocal = getVTracksReservedLocal();
KnikEngine* knik = KnikEngine::get( getCell() );
if (knik) {
hTracksReservedLocal = knik->getHEdgeReservedLocal();
vTracksReservedLocal = knik->getVEdgeReservedLocal();
}
if (cparanoid.enabled()) {
cparanoid << " o Post-checking Knik capacity overload h:" << hTracksReservedLocal
<< " v:." << vTracksReservedLocal << endl;
getGCellGrid()->checkEdgeOverflow( hTracksReservedLocal, vTracksReservedLocal );
}
_check( overlaps );
Session::close();
_toolSuccess = _toolSuccess and (overlaps == 0);
}
void KiteEngine::printCompletion () const
{
size_t routeds = 0;
unsigned long long totalWireLength = 0;
unsigned long long routedWireLength = 0;
vector<TrackElement*> unrouteds;
vector<TrackElement*> reduceds;
ostringstream result;
AutoSegmentLut::const_iterator ilut = _getAutoSegmentLut().begin();
for ( ; ilut != _getAutoSegmentLut().end() ; ilut++ ) {
TrackElement* segment = _lookup( ilut->second );
if (segment == NULL) continue;
unsigned long long wl = (unsigned long long)DbU::toLambda( segment->getLength() );
if (wl > 100000) {
cerr << Error("KiteEngine::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 );
}
float segmentRatio = (float)(routeds) / (float)(routeds+unrouteds.size()) * 100.0;
float wireLengthRatio = (float)(routedWireLength) / (float)(totalWireLength) * 100.0;
_toolSuccess = (unrouteds.empty());
if (not unrouteds.empty()) {
cerr << " o Routing did not complete, unrouted segments:" << endl;
for ( size_t i=0; i<unrouteds.size() ; ++i ) {
cerr << " " << dec << setw(4) << (i+1) << "| " << unrouteds[i] << endl;
}
}
// if (not reduceds.empty()) {
// cerr << " o Reduced segments:" << endl;
// for ( size_t i=0; i<reduceds.size() ; ++i ) {
// cerr << " " << dec << setw(4) << (i+1) << "| " << reduceds[i] << endl;
// }
// }
result << setprecision(4) << segmentRatio
<< "% [" << routeds << "+" << unrouteds.size() << "]";
cmess1 << Dots::asString( " - Track Segment Completion Ratio", result.str() ) << endl;
result.str("");
result << setprecision(4) << wireLengthRatio
<< "% [" << totalWireLength << "+"
<< (totalWireLength - routedWireLength) << "]";
cmess1 << Dots::asString( " - Wire Length Completion Ratio", result.str() ) << endl;
float expandRatio = 1.0;
if (_minimumWL != 0.0) {
expandRatio = ((totalWireLength-_minimumWL) / _minimumWL) * 100.0;
result.str("");
result << setprecision(3) << expandRatio << "% [min:" << setprecision(9) << _minimumWL << "]";
cmess1 << Dots::asString( " - Wire Length Expand Ratio", result.str() ) << endl;
}
addMeasure<size_t> ( getCell(), "Segs" , routeds+unrouteds.size() );
addMeasure<unsigned long long>( getCell(), "DWL(l)" , totalWireLength , 12 );
addMeasure<unsigned long long>( getCell(), "fWL(l)" , totalWireLength-routedWireLength , 12 );
addMeasure<double> ( getCell(), "WLER(%)", (expandRatio-1.0)*100.0 );
}
void KiteEngine::dumpMeasures ( ostream& out ) const
{
vector<Name> measuresLabels;
measuresLabels.push_back( "Gates" );
measuresLabels.push_back( "GCells" );
measuresLabels.push_back( "knikT" );
measuresLabels.push_back( "knikS" );
measuresLabels.push_back( "GWL(l)" );
measuresLabels.push_back( "Area(l2)");
measuresLabels.push_back( "Sat." );
measuresLabels.push_back( "loadT" );
measuresLabels.push_back( "loadS" );
measuresLabels.push_back( "Globals" );
measuresLabels.push_back( "Edges" );
measuresLabels.push_back( "assignT" );
measuresLabels.push_back( "algoT" );
measuresLabels.push_back( "algoS" );
measuresLabels.push_back( "finT" );
measuresLabels.push_back( "Segs" );
measuresLabels.push_back( "DWL(l)" );
measuresLabels.push_back( "fWL(l)" );
measuresLabels.push_back( "WLER(%)" );
measuresLabels.push_back( "Events" );
measuresLabels.push_back( "UEvents" );
const MeasuresSet* measures = Measures::get( getCell() );
out << "#" << endl;
out << "# " << getCell()->getName() << endl;
out << measures->toStringHeaders(measuresLabels) << endl;
out << measures->toStringDatas (measuresLabels) << endl;
measures->toGnuplot( "GCells Density Histogram", getString(getCell()->getName()) );
}
void KiteEngine::dumpMeasures () const
{
ostringstream path;
path << getCell()->getName() << ".knik-kite.dat";
ofstream sfile ( path.str().c_str() );
dumpMeasures( sfile );
sfile.close();
}
bool KiteEngine::_check ( unsigned int& overlap, const char* message ) const
{
cmess1 << " o Checking Kite Database coherency." << endl;
bool coherency = true;
coherency = coherency and KatabaticEngine::_check( message );
for ( size_t i=0 ; i<_routingPlanes.size() ; i++ )
coherency = _routingPlanes[i]->_check(overlap) and coherency;
Katabatic::Session* ktbtSession = Session::base ();
for( Net* net : getCell()->getNets() ) {
for( Segment* segment : net->getComponents().getSubSet<Segment*>() ) {
AutoSegment* autoSegment = ktbtSession->lookup( segment );
if (not autoSegment) continue;
if (not autoSegment->isCanonical()) continue;
TrackElement* trackSegment = Session::lookup( segment );
if (not trackSegment) {
coherency = false;
cerr << Bug( "%p %s without Track Segment"
, autoSegment
, getString(autoSegment).c_str() ) << endl;
} else
trackSegment->_check();
}
}
return coherency;
}
void KiteEngine::finalizeLayout ()
{
cdebug_log(155,0) << "KiteEngine::finalizeLayout()" << endl;
if (getState() > Katabatic::EngineDriving) return;
cdebug_tabw(155,1);
setState( Katabatic::EngineDriving );
_gutKite();
KatabaticEngine::finalizeLayout();
cdebug_log(155,0) << "State: " << getState() << endl;
getCell()->setFlags( Cell::Flags::Routed );
cdebug_tabw(155,-1);
}
void KiteEngine::_gutKite ()
{
cdebug_log(155,1) << "KiteEngine::_gutKite()" << endl;
cdebug_log(155,0) << "State: " << getState() << endl;
if (getState() < Katabatic::EngineGutted) {
Session::open( this );
size_t maxDepth = getRoutingGauge()->getDepth();
for ( size_t depth=0 ; depth < maxDepth ; depth++ ) {
_routingPlanes[depth]->destroy();
}
Session::close();
}
cdebug_tabw(155,-1);
}
TrackElement* KiteEngine::_lookup ( Segment* segment ) const
{
AutoSegment* autoSegment = KatabaticEngine::_lookup( segment );
if (not autoSegment or not autoSegment->isCanonical()) return NULL;
return _lookup( autoSegment );
}
void KiteEngine::_check ( Net* net ) const
{
cerr << " o Checking " << net << endl;
for( Segment* segment : net->getComponents().getSubSet<Segment*>() ) {
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 KiteEngine::_getTypeName () const
{ return "Kite::KiteEngine"; }
string KiteEngine::_getString () const
{
ostringstream os;
os << "<" << "KiteEngine " << _cell->getName () << ">";
return os.str();
}
Record* KiteEngine::_getRecord () const
{
Record* record = KatabaticEngine::_getRecord ();
if (record) {
record->add( getSlot( "_routingPlanes", &_routingPlanes ) );
record->add( getSlot( "_configuration", _configuration ) );
}
return record;
}
} // Kite namespace.