coriolis/katana/src/KatanaEngine.cpp

1020 lines
33 KiB
C++

// -*- 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 <Python.h>
#include <sstream>
#include <fstream>
#include <iomanip>
#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<KatanaEngine*>(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<size_t>( "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<Isobar::Script> 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<Configuration*>( Super::getConfiguration() ); }
const Configuration* KatanaEngine::getConfiguration () const
{ return static_cast<const Configuration*>( 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<GCell*> 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 ; itrack<tracksSize ; ++itrack ) {
Track* track = rp->getTrackByIndex( 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 ; 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;
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 ; i<gcells->size()-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 ; i<gcells->size()-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<DbU::Unit> terminalsX;
for ( Component* component : getCell()->getComponentsUnder(gcell->getBoundingBox()) ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( 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<size_t>( "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<TrackElement*> unrouteds;
vector<TrackElement*> reduceds;
ostringstream result;
bool isSymbolic =
const_cast<KatanaEngine*>(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<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;
// }
// }
string units = "L";
if (not isSymbolic) {
units = "um";
totalWireLength /= 1000;
routedWireLength /= 1000;
}
result << setprecision(4) << segmentRatio
<< "% [" << routeds << "+" << unrouteds.size() << "]";
cmess1 << Dots::asString( " - Track Segment Completion Ratio", result.str() ) << endl;
result.str("");
result << setprecision(4) << wireLengthRatio
<< "% [" << totalWireLength << units << "+"
<< (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 << units << "]";
cmess1 << Dots::asString( " - Wire Length Expand Ratio", result.str() ) << endl;
}
float ratio = 0.0;
if (not unrouteds.empty())
ratio = ((float)hunrouteds / (float)unrouteds.size()) * 100.0;
result.str("");
result << setprecision(4) << ratio << "% [" << hunrouteds << "]";
cmess1 << Dots::asString( " - Unrouted horizontals", result.str() ) << endl;
if (not unrouteds.empty())
ratio = ((float)vunrouteds / (float)unrouteds.size()) * 100.0;
result.str("");
result << setprecision(4) << ratio << "% [" << vunrouteds << "]";
cmess1 << Dots::asString( " - Unrouted verticals", result.str() ) << endl;
addMeasure<size_t> ( "Segs" , routeds+unrouteds.size() );
addMeasure<uint64_t>( "DWL" , totalWireLength , 12 );
addMeasure<uint64_t>( "fWL" , totalWireLength-routedWireLength , 12 );
addMeasure<double> ( "WLER(%)", expandRatio );
}
void KatanaEngine::dumpMeasures ( ostream& out ) const
{
vector<Name> 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<Segment*>() ) {
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<Component*> removeds;
for ( Component* component : net->getComponents() ) {
if (dynamic_cast<Plug *>(component)) continue;
if (dynamic_cast<Contact*>(component)) removeds.push_back( component );
}
for ( Component* component : removeds ) component->destroy();
}
for ( Net* net : getCell()->getNets() ) {
vector<Component*> removeds;
for ( Component* component : net->getComponents() ) {
if (dynamic_cast<Plug*>(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<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 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.