coriolis/katana/src/NegociateWindow.cpp

906 lines
30 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 : "./NegociateWindow.cpp" |
// +-----------------------------------------------------------------+
#include <vector>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include "hurricane/Breakpoint.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#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 "anabatic/AutoContact.h"
#include "katana/DataNegociate.h"
#include "katana/TrackElement.h"
#include "katana/TrackMarker.h"
#include "katana/TrackCost.h"
#include "katana/Track.h"
#include "katana/TrackSegment.h"
#include "katana/RoutingPlane.h"
#include "katana/RoutingEventQueue.h"
#include "katana/RoutingEventHistory.h"
#include "katana/RoutingEventLoop.h"
#include "katana/NegociateWindow.h"
#include "katana/KatanaEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace CRL;
using namespace Katana;
void NegociateOverlapCost ( const TrackElement* segment, TrackCost& cost )
{
cdebug_log(159,1) << "NegociateOverlapCost() " << segment << endl;
Interval intersect = segment->getCanonicalInterval();
if (not intersect.intersect(cost.getInterval())) {
cdebug_tabw(159,-1);
return;
}
if (segment->getNet() != cost.getNet()) {
cdebug_log(159,0) << segment->getNet() << " vs. " << cost.getNet() << endl;
if ( segment->isBlockage()
or (segment->isFixed()
and not (segment->isVertical() and Session::getKatanaEngine()->isChannelStyle()))) {
cdebug_log(159,0) << "Infinite cost from: " << segment << endl;
cost.setInfinite ();
cost.setOverlap ();
cost.setHardOverlap();
cost.setBlockage ();
cdebug_tabw(159,-1);
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() );
else {
DbU::Unit beginOverlap = cost.getInterval().getVMin() - intersect.getVMin();
DbU::Unit endOverlap = intersect.getVMax() - cost.getInterval().getVMax();
cost.setLonguestOverlap( std::min( beginOverlap, endOverlap ) );
cost.setGlobalEnclosed();
}
DataNegociate* data = segment->getDataNegociate();
if (not data) {
cdebug_tabw(159,-1);
return;
}
TrackElement* refSegment = cost.getRefElement();
DataNegociate* refData = refSegment->getDataNegociate();
AutoSegment* refBase = refSegment->base();
AutoSegment* base = segment->base();
if (base and refBase and refData) {
if ( ( base->getRpDistance() == 0)
and (refBase->getRpDistance() > 0)
and (refData->getState() > DataNegociate::RipupPerpandiculars)
and ( data->getState() == DataNegociate::RipupPerpandiculars)
and ( data->getRipupCount() > 4)) {
cost.setAtRipupLimit();
}
if ( refSegment->isNonPref()
and segment->isUnbreakable()
and (data->getState() >= DataNegociate::Minimize)
and (data->getStateCount() >= 2) ) {
cost.setAtRipupLimit();
}
}
cost.mergeRipupCount( data->getRipupCount() );
if (segment->isLocal()) {
cost.mergeDataState( data->getState() );
if (data->getState() >= DataNegociate::LocalVsGlobal) {
cdebug_log(159,0) << "MaximumSlack/LocalVsGlobal for " << segment << endl;
cost.setAtRipupLimit();
}
}
if (data->getState() == DataNegociate::MaximumSlack) {
cost.setAtRipupLimit();
}
if (segment->isGlobal()) {
cost.setOverlapGlobal();
if ( (cost.getFlags() & TrackCost::LocalAndTopDepth)
and (data->getState() >= DataNegociate::MoveUp) ) {
cost.setInfinite ();
cost.setOverlap ();
cost.setHardOverlap();
cdebug_tabw(159,-1);
return;
}
}
cost.setOverlap();
if ( segment->isLocal()
or (cost.isForGlobal() and (Session::getRoutingGauge()->getLayerDepth(segment->getLayer()) < 3)) ) {
cdebug_log(9000,0) << "Deter| incTerminals() " << boolalpha << cost.isForGlobal() << " " << (data->getTerminals()*100) << endl;
cost.incTerminals( data->getTerminals()*100 );
} else {
cdebug_log(9000,0) << "Deter| isForGlobal() " << boolalpha << cost.isForGlobal() << endl;
}
cdebug_log(159,0) << "| Increment Delta: " << DbU::getValueString(intersect.getSize()) << endl;
cost.incDelta( intersect.getSize() );
// if (segment->base()->getId() == 70433) {
// cdebug_log(159,0) << "| G:" << cost.isForGlobal()
// << " L:" << segment->isLocal()
// << " rpD:" << segment->base()->getRpDistance()
// << " state:" << data->getState()
// << " (Dogleg:" << DataNegociate::Dogleg
// << ") ripup:" << data->getRipupCount()
// << endl;
// }
if ( cost.isForGlobal()
and segment->isLocal()
and (segment->base()->getRpDistance() < 2)
and (data->getState() >= DataNegociate::Dogleg)
//and (data->getRipupCount() > Session::getConfiguration()->getRipupLimit(Configuration::LocalRipupLimit) - 2)
) {
cost.setInfinite();
cdebug_log(159,0) << "Infinite cost from (RP access)" << segment << endl;
}
cdebug_tabw(159,-1);
}
void loadRoutingPads ( NegociateWindow* nw )
{
AllianceFramework* af = AllianceFramework::get ();
RoutingGauge* rg = nw->getKatanaEngine()->getConfiguration()->getRoutingGauge();
//bool isVH = rg->isVH();
for( Net* net : nw->getCell()->getNets() ) {
if (net->getType() == Net::Type::POWER ) continue;
if (net->getType() == Net::Type::GROUND) continue;
//if (net->getType() == Net::Type::CLOCK ) continue;
if (af->isBLOCKAGE(net->getName())) continue;
for( RoutingPad* rp : net->getRoutingPads() ) {
size_t depth = rg->getLayerDepth(rp->getLayer());
size_t rlDepth = depth - rg->getFirstRoutingLayer();
if (rlDepth == 0) {
TrackMarker::create( rp, depth+1 );
//if (isVH) TrackMarker::create( rp, depth+2 );
}
if (rlDepth == 1) {
if (depth+1 < rg->getDepth())
TrackMarker::create( rp, depth+1 );
}
}
}
}
class CompareByPriority {
public:
inline bool operator() ( const TrackSegment* lhs, const TrackSegment* rhs )
{ return lhs->getPriority() > rhs->getPriority(); }
};
void computeNetPriority ( Net* net )
{
DebugSession::open( net, 159, 160 );
cdebug_log(159,1) << "::computeNetPriority() " << net << endl;
vector<TrackSegment*> segments;
for ( Segment* segment : net->getSegments() ) {
TrackSegment* canonical = dynamic_cast<TrackSegment*>( Session::lookup( segment ) );
if (canonical) segments.push_back( canonical );
}
for ( TrackSegment* segment : segments ) segment->computePriority();
sort( segments.begin(), segments.end(), CompareByPriority() );
for ( TrackSegment* segment : segments ) {
segment->computeAlignedPriority();
}
cdebug_tabw(159,-1);
DebugSession::close();
}
} // Anonymous namespace.
namespace Katana {
using std::ofstream;
using std::cerr;
using std::endl;
using std::setw;
using std::left;
using std::right;
using std::setprecision;
using Hurricane::Breakpoint;
using Hurricane::Warning;
using Hurricane::Bug;
using Hurricane::tab;
using Hurricane::ForEachIterator;
using Hurricane::DebugSession;
using Hurricane::UpdateSession;
using CRL::Histogram;
using CRL::addMeasure;
using Anabatic::AutoContact;
using Anabatic::AutoSegment;
using Anabatic::AutoSegmentLut;
using Anabatic::perpandicularTo;
// -------------------------------------------------------------------
// Class : "NegociateWindow".
NegociateWindow::NegociateWindow ( KatanaEngine* katana )
: _flags (Flags::NoFlags)
, _interrupt (false)
, _katana (katana)
, _gcells ()
, _segments ()
, _eventQueue ()
, _eventHistory()
, _eventLoop (10,70)
{ }
NegociateWindow* NegociateWindow::create ( KatanaEngine* katana )
{
NegociateWindow* negociateWindow = new NegociateWindow ( katana );
return negociateWindow;
}
NegociateWindow::~NegociateWindow ()
{ }
void NegociateWindow::destroy ()
{ delete this; }
Cell* NegociateWindow::getCell () const
{ return _katana->getCell(); }
void NegociateWindow::setGCells ( const vector<GCell*>& gcells )
{
_gcells = gcells;
if (not Session::getKatanaEngine()->isChannelStyle()) loadRoutingPads( this );
Session::revalidate();
for ( auto element : Session::getKatanaEngine()->_getAutoSegmentLut() ) {
TrackElement* segment = Session::lookup( element.second );
if (segment) segment->getDataNegociate()->update();
}
_statistics.setGCellsCount( _gcells.size() );
}
void NegociateWindow::addRoutingEvent ( TrackElement* segment, uint32_t level )
{
DataNegociate* data = segment->getDataNegociate();
if (not data or not data->hasRoutingEvent())
_eventQueue.add( segment, level );
else
cerr << Bug( "NegociateWidow::addRoutingEvent(): Try to adds twice the same TrackElement event."
"\n %p:%s."
, (void*)segment->base()->base()
, getString(segment).c_str()
) << endl;
}
TrackElement* NegociateWindow::createTrackSegment ( AutoSegment* autoSegment, Flags flags )
{
DebugSession::open( autoSegment->getNet(), 159, 160 );
cdebug_log(159,1) << "NegociateWindow::createTrackSegment() - " << autoSegment << endl;
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
Track* refTrack = plane->getTrackByPosition( autoSegment->getAxis() );
Track* insTrack = NULL;
size_t trackSpan = 1;
// Special case: fixed AutoSegments must not interfere with blockages.
// Ugly: uses of getExtensionCap().
if (autoSegment->isFixed()) {
if (Session::isChannelStyle() and autoSegment->isReduced()) {
cdebug_log(159,0) << "* Fixed segment is reduced, ignore " << autoSegment << endl;
cdebug_tabw(159,-1);
return NULL;
}
size_t begin;
size_t end;
Interval fixedSpan;
Interval blockageSpan;
if (Session::isChannelStyle() and autoSegment->isNonPref()) {
cdebug_log(159,0) << "Fixed in non-preferred direction, do not attempt to set on track." << endl;
cdebug_tabw(159,-1);
DebugSession::close();
return NULL;
}
if (not refTrack) {
string message = "NULL refTrack for " + getString(autoSegment) + " brace for crashing!";
Breakpoint::stop( 0, message );
}
if (refTrack->getAxis() != autoSegment->getAxis()) {
trackSpan = 2;
refTrack = plane->getTrackByPosition( autoSegment->getAxis(), Constant::Inferior );
insTrack = refTrack;
}
Track* track = refTrack;
for ( size_t ispan=0 ; track and (ispan < trackSpan) ; ++ispan, track=track->getNextTrack() ) {
autoSegment->getCanonical( fixedSpan );
fixedSpan.inflate( Session::getExtensionCap(autoSegment->getLayer())-1 );
track->getOverlapBounds( fixedSpan, begin, end );
for ( ; (begin < end) ; begin++ ) {
TrackElement* other = track->getSegment(begin);
cdebug_log(159,0) << "| overlap: " << other << endl;
if (not other->isBlockage()) continue;
other->getCanonical( blockageSpan );
blockageSpan.inflate( Session::getExtensionCap(autoSegment->getLayer()) );
cdebug_log(159,0) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl;
if (not fixedSpan.intersect(blockageSpan)) continue;
// Overlap between fixed & blockage.
cdebug_log(159,0) << "* 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;
cdebug_tabw(159,-1);
DebugSession::close();
return NULL;
}
}
}
Interval span;
autoSegment = autoSegment->getCanonical( span );
bool created;
TrackElement* trackSegment = TrackSegment::create( autoSegment, insTrack, created );
if (not (flags & Flags::LoadingStage))
cdebug_log(159,0) << "* lookup: " << autoSegment << endl;
if (created) {
cdebug_log(159,0) << "* " << trackSegment << endl;
if (trackSegment->isNonPref()) {
_segments.push_back( trackSegment );
cdebug_log(159,0) << "Non-preferred direction, do not attempt to set on track." << endl;
cdebug_tabw(159,-1);
DebugSession::close();
return trackSegment;
}
Interval uside = autoSegment->getAutoSource()->getGCell()->getSide( perpandicularTo(autoSegment->getDirection()) );
Interval constraints;
autoSegment->getConstraints( constraints );
cdebug_log(159,0) << "* Constraints " << constraints << endl;
uside.intersection( constraints );
cdebug_log(159,0) << "* Constraints+U-side " << constraints << endl;
cdebug_log(159,0) << "* Nearest " << refTrack << endl;
if (not refTrack)
throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s."
, getString(autoSegment).c_str() );
if (not insTrack) {
insTrack = refTrack;
if (refTrack->getAxis() > uside.getVMax()) insTrack = refTrack->getPreviousTrack();
if (refTrack->getAxis() < uside.getVMin()) insTrack = refTrack->getNextTrack();
}
if (not insTrack)
throw Error( "NegociateWindow::createTrackSegment(): No track near axis of %s (after adjust)."
, getString(autoSegment).c_str() );
cdebug_log(159,0) << "* GCell U-side " << uside << endl;
cdebug_log(159,0) << "* " << plane << endl;
cdebug_log(159,0) << "* " << insTrack << endl;
if (trackSpan == 1)
trackSegment->setAxis( insTrack->getAxis(), AutoSegment::SegAxisSet );
trackSegment->invalidate();
if (trackSegment->isFixed() and not trackSegment->getTrack()) {
Session::addInsertEvent( trackSegment, insTrack, refTrack->getAxis() );
} else {
_segments.push_back( trackSegment );
}
}
if (not created and not (flags & Flags::LoadingStage)) {
cdebug_log(159,0) << "TrackSegment already exists (and not in loading stage)." << endl;
}
cdebug_tabw(159,-1);
DebugSession::close();
return trackSegment;
}
double NegociateWindow::computeWirelength ()
{
bool isSymbolic = getKatanaEngine()->getConfiguration()->getRoutingGauge()->isSymbolic();
set<TrackElement*> accounteds;
double totalWL = 0.0;
for ( size_t igcell=0 ; igcell<_gcells.size() ; ++igcell ) {
double gcellWL = 0.0;
Segment* segment;
TrackElement* trackSegment;
const vector<AutoContact*>& contacts = _gcells[igcell]->getContacts();
for ( size_t i=0 ; i<contacts.size() ; i++ ) {
for( Hook* hook : contacts[i]->getBodyHook()->getSlaveHooks() ) {
Hook* sourceHook = dynamic_cast<Segment::SourceHook*>(hook);
if (not sourceHook) continue;
segment = dynamic_cast<Segment*>(sourceHook->getComponent());
trackSegment = Session::lookup( segment );
if (trackSegment) {
if (accounteds.find(trackSegment) != accounteds.end()) continue;
accounteds.insert( trackSegment );
if (isSymbolic)
gcellWL += DbU::getLambda( trackSegment->getLength() );
else
gcellWL += DbU::toPhysical( trackSegment->getLength(), DbU::UnitPower::Nano );
}
}
}
// Partial sum to limit rounding errors.
totalWL += gcellWL;
}
if (not isSymbolic) totalWL /= 1000.0;
return totalWL;
}
void NegociateWindow::_computePriorities ()
{
for ( Net* net : getCell()->getNets() ) {
if (NetRoutingExtension::isAnalog(net)) computeNetPriority( net );
}
}
void NegociateWindow::_createRouting ( Anabatic::GCell* gcell )
{
cdebug_log(159,1) << "NegociateWindow::_createRouting() - " << gcell << endl;
Segment* segment;
AutoSegment* autoSegment;
cdebug_log(159,0) << "AutoSegments from AutoContacts" << endl;
const vector<AutoContact*>& contacts = gcell->getContacts();
for ( size_t i=0 ; i<contacts.size() ; i++ ) {
for( Component* component : contacts[i]->getSlaveComponents() ) {
segment = dynamic_cast<Segment*>(component);
autoSegment = Session::base()->lookup( segment );
cdebug_log(159,0) << autoSegment << endl;
if (autoSegment and autoSegment->isCanonical()) {
createTrackSegment( autoSegment, Flags::LoadingStage );
}
}
}
cdebug_log(159,0) << "_segments.size():" << _segments.size() << endl;
cdebug_tabw(159,-1);
}
void NegociateWindow::_pack ( size_t& count, bool last )
{
uint64_t limit = _katana->getEventsLimit();
_katana->setStage( StagePack );
RoutingEventQueue packQueue;
//for ( size_t i = (count > 600) ? count-600 : 0
// ; (i<_eventHistory.size()-(last ? 0 : 100)) and not isInterrupted() ; i++ ) {
for ( size_t i=0 ; i<_eventHistory.size() ; ++i ) {
RoutingEvent* event = _eventHistory.getNth(i);
if ( event and not event->isCloned() ) {
cerr << "Cloned:" << event->isCloned()
<< " UTurn:" << event->getSegment()->isUTurn() << " " << event->getSegment() << endl;
}
if ( event and not event->isCloned() and event->getSegment()->isUTurn() ) {
event->reschedule( packQueue, 0 );
}
}
packQueue.commit();
while ( not packQueue.empty() and not isInterrupted() ) {
RoutingEvent* event = packQueue.pop();
if (tty::enabled()) {
cmess2 << " <pack.event:" << tty::bold << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << tty::reset
<< " remains:" << right << setw(8) << setfill('0')
<< packQueue.size() << ">"
<< setfill(' ') << tty::reset << tty::cr;
cmess2.flush();
} else {
cmess2 << " <pack.event:" << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
<< event->getEventLevel() << ":" << event->getPriority() << "> "
<< event->getSegment()
<< endl;
cmess2.flush();
}
event->process( packQueue, _eventHistory, _eventLoop );
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
}
// Count will be wrong!
}
size_t NegociateWindow::_negociate ()
{
cdebug_log(9000,0) << "Deter| NegociateWindow::_negociate()" << endl;
cdebug_log(159,1) << "NegociateWindow::_negociate() - " << _segments.size() << endl;
cmess1 << " o Negociation Stage." << endl;
unsigned long limit = _katana->getEventsLimit();
bool profiling = _katana->profileEventCosts();
ofstream ofprofile;
if (profiling) ofprofile.open( "katana.profile.txt" );
_eventHistory.clear();
_eventQueue.load( _segments );
cmess2 << " <queue:" << right << setw(8) << setfill('0') << _eventQueue.size() << ">" << endl;
if (cdebug.enabled(9000)) _eventQueue.dump();
size_t count = 0;
_katana->setStage( StageNegociate );
while ( not _eventQueue.empty() and not isInterrupted() ) {
RoutingEvent* event = _eventQueue.pop();
if (ofprofile.is_open()) {
size_t depth = _katana->getConfiguration()->getLayerDepth( event->getSegment()->getLayer() );
if (depth < 6) {
ofprofile << setw(10) << right << count << " ";
for ( size_t i=0 ; i<6 ; ++i ) {
if (i == depth)
ofprofile << setw(10) << right << setprecision(2) << event->getPriority() << " ";
else
ofprofile << setw(10) << right << setprecision(2) << 0.0 << " ";
}
ofprofile << setw( 2) << right << event->getEventLevel() << endl;
}
}
if (tty::enabled()) {
cmess2 << " <event:" << tty::bold << right << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << tty::reset
<< " remains:" << right << setw(8) << setfill('0')
<< _eventQueue.size()
<< setfill(' ') << tty::reset << ">" << tty::cr;
cmess2.flush ();
} else {
cmess2 << " <event:" << right << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
<< event->getEventLevel() << ":" << event->getPriority()
<< ":" << DbU::getValueString(event->getSegment()->getLength()) << "> "
<< event->getSegment()
<< endl;
cmess2.flush();
}
//if (RoutingEvent::getProcesseds() == 14473)
// Breakpoint::stop( 0, "Before processing RoutingEvent 14473." );
event->process( _eventQueue, _eventHistory, _eventLoop );
count++;
// if (event->getSegment()->getNet()->getId() == 239546) {
// UpdateSession::close();
// ostringstream message;
// message << "After processing an event from Net id:239546\n" << event;
// Breakpoint::stop( 0, message.str() );
// UpdateSession::open();
// }
//if (count and not (count % 500)) {
// _pack( count, false );
//}
// if (RoutingEvent::getProcesseds() == 65092) {
// UpdateSession::close();
// Breakpoint::stop( 0, "Overlap has happened" );
// UpdateSession::open();
// }
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
}
//_pack( count, true );
_negociateRepair();
if (_katana->getConfiguration()->runRealignStage()) {
cmess1 << " o Realign Stage." << endl;
cdebug_log(159,0) << "Loadind realign queue." << endl;
_katana->setStage( StageRealign );
for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) {
RoutingEvent* event = _eventHistory.getNth(i);
if (not event->isCloned() and event->getSegment()->canRealign())
event->reschedule( _eventQueue, 0 );
}
_eventQueue.commit();
cmess2 << " <realign.queue:" << right << setw(8) << setfill('0')
<< _eventQueue.size() << ">" << setfill(' ') << endl;
count = 0;
while ( not _eventQueue.empty() and not isInterrupted() ) {
RoutingEvent* event = _eventQueue.pop();
if (tty::enabled()) {
cmess2 << " <realign.event:" << tty::bold << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << tty::reset
<< " remains:" << right << setw(8) << setfill('0')
<< _eventQueue.size() << ">"
<< setfill(' ') << tty::reset << tty::cr;
cmess2.flush();
} else {
cmess2 << " <realign.event:" << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
<< event->getEventLevel() << ":" << event->getPriority() << "> "
<< event->getSegment()
<< endl;
cmess2.flush();
}
event->process( _eventQueue, _eventHistory, _eventLoop );
count++;
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
}
_negociateRepair();
}
if (count and cmess2.enabled() 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 (ofprofile.is_open()) ofprofile.close();
_statistics.setEventsCount( eventsCount );
cdebug_tabw(159,-1);
return eventsCount;
}
void NegociateWindow::_negociateRepair ()
{
cdebug_log(159,1) << "NegociateWindow::_negociateRepair() - " << _segments.size() << endl;
uint64_t limit = _katana->getEventsLimit();
uint64_t count = 0;
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
cmess1 << " o Repair Stage." << endl;
cdebug_log(159,0) << "Loadind Repair queue." << endl;
_katana->setStage( StageRepair );
for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) {
RoutingEvent* event = _eventHistory.getNth(i);
if (not event->isCloned() and (event->getState() >= DataNegociate::Unimplemented)) {
event->setState( DataNegociate::Repair );
event->reschedule( _eventQueue, 0 );
}
}
_eventQueue.commit();
cmess2 << " <repair.queue:" << right << setw(8) << setfill('0')
<< _eventQueue.size() << ">" << setfill(' ') << endl;
while ( not _eventQueue.empty() and not isInterrupted() ) {
RoutingEvent* event = _eventQueue.pop();
if (tty::enabled()) {
cmess2 << " <repair.event:" << tty::bold << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << tty::reset
<< " remains:" << right << setw(8) << setfill('0')
<< _eventQueue.size() << ">"
<< setfill(' ') << tty::reset << tty::cr;
cmess2.flush();
} else {
cmess2 << " <repair.event:" << setw(8) << setfill('0')
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
<< event->getEventLevel() << ":" << event->getPriority() << "> "
<< event->getSegment()
<< endl;
cmess2.flush();
}
event->process( _eventQueue, _eventHistory, _eventLoop );
count++;
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
}
cdebug_tabw(159,-1);
}
void NegociateWindow::run ( Flags flags )
{
cdebug_log(159,1) << "NegociateWindow::run()" << endl;
cmess1 << " o Running Negociate Algorithm" << endl;
TrackElement::setOverlapCostCB( NegociateOverlapCost );
RoutingEvent::resetProcesseds();
for ( size_t igcell=0 ; igcell<_gcells.size() ; ++igcell ) {
_createRouting( _gcells[igcell] );
}
Session::revalidate();
_computePriorities();
if (not (flags & Flags::PreRoutedStage)) {
_katana->preProcess();
_katana->_computeCagedConstraints();
Session::revalidate();
}
_katana->setMinimumWL( computeWirelength() );
#if defined(CHECK_DATABASE)
uint32_t overlaps = 0;
Session::getKatanaEngine()->_check( overlaps, "after _createRouting(GCell*)" );
#endif
if (flags & Flags::PairSymmetrics) {
_katana->pairSymmetrics();
Session::revalidate();
}
_flags |= flags;
_negociate();
printStatistics();
if (flags & Flags::PreRoutedStage) {
_katana->setFixedPreRouted();
}
Session::revalidate();
for ( RoutingPlane* plane : _katana->getRoutingPlanes() ) {
for ( Track* track : plane->getTracks() )
track->repair();
}
Session::revalidate();
Session::get()->isEmpty();
# if defined(CHECK_DATABASE)
_katana->_check( overlaps, "after negociation" );
# endif
cdebug_tabw(159,-1);
}
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;
_katana->printCompletion();
_katana->addMeasure<size_t>( "Events" , RoutingEvent::getProcesseds(), 12 );
_katana->addMeasure<size_t>( "UEvents", RoutingEvent::getProcesseds()-RoutingEvent::getCloneds(), 12 );
Histogram* densityHistogram = new Histogram ( 1.0, 0.1, 2 );
_katana->addMeasure<Histogram>( "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 vector<GCell*>& gcells = getKatanaEngine()->getGCells();
getKatanaEngine()->setDensityMode( Anabatic::AnabaticEngine::MaxHVDensity );
for ( size_t igcell=0 ; igcell<gcells.size() ; ++igcell ) {
densityHistogram->addSample( gcells[igcell]->getDensity(), 0 );
}
getKatanaEngine()->setDensityMode( Anabatic::AnabaticEngine::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;
}
} // Katana namespace.