coriolis/katana/src/TrackCost.cpp

305 lines
11 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 : "./TrackCost.cpp" |
// +-----------------------------------------------------------------+
#include <cstdlib>
#include <sstream>
#include <iostream>
#include "katana/Track.h"
#include "katana/TrackCost.h"
#include "katana/TrackElement.h"
#include "katana/Session.h"
namespace Katana {
using std::cerr;
using std::endl;
using Hurricane::Error;
// -------------------------------------------------------------------
// Class : "TrackCost".
TrackCost::TrackCost ( TrackElement* refSegment
, TrackElement* symSegment
, Track* refTrack
, Track* symTrack
, DbU::Unit refCandidateAxis
, DbU::Unit symCandidateAxis
)
: _flags ((symSegment) ? Symmetric : NoFlags)
, _span (refSegment->getTrackSpan())
, _refCandidateAxis(refCandidateAxis)
, _symCandidateAxis(symCandidateAxis)
, _tracks ( _span * ((symSegment) ? 2 : 1)
, std::tuple<Track*,size_t,size_t>(NULL,Track::npos,Track::npos) )
, _segment1 (refSegment)
, _segment2 (symSegment)
, _interval1 (refSegment->getCanonicalInterval())
, _interval2 ((symSegment) ? symSegment->getCanonicalInterval() : Interval())
, _terminals (0)
, _delta (-_interval1.getSize() -_interval2.getSize())
, _deltaShared (0)
, _deltaPerpand (0)
, _axisWeight (0)
, _distanceToFixed (2*Session::getSliceHeight())
, _longuestOverlap (0)
, _dataState (0)
, _ripupCount (0)
, _selectFlags (NoFlags)
, _selectIndex (0)
{
if (refSegment->isNonPref()) {
DbU::Unit axisShift = getRefCandidateAxis() - refSegment->getAxis();
_interval1.translate( axisShift );
if (symSegment) {
throw Error( "TrackCost::TrackCost(): Symmetric management is not implemented for Non-preferred routing segments.\n"
" %s", getString(refSegment).c_str() );
}
}
if (not _span) {
throw Error( "TrackCost::TrackCost(): Zero track span is not allowed.\n"
" %s", getString(refSegment).c_str() );
}
cdebug_log(159,1) << "TrackCost::TrackCost() - " << refSegment << endl;
cdebug_log(159,0) << " interval1: " << _interval1 << endl;
std::get<0>( _tracks[0] ) = refTrack;
_segment1->addOverlapCost( *this );
if (symTrack) {
cdebug_log(159,0) << " _tracks.size(): " << _tracks.size() << " _span:" << _span << endl;
std::get<0>( _tracks[_span] ) = symTrack;
select( 0, Symmetric );
_segment2->addOverlapCost( *this );
}
consolidate();
cdebug_tabw(159,-1);
}
TrackCost::~TrackCost ()
{ }
bool TrackCost::isFree () const
{
return /*(not _terminals) and*/ (not isOverlap()) and (not isInfinite());
}
bool TrackCost::Compare::operator() ( const TrackCost* lhs, const TrackCost* rhs )
{
if ( lhs->isInfinite () xor rhs->isInfinite () ) return rhs->isInfinite();
if ( lhs->isAtRipupLimit() xor rhs->isAtRipupLimit() ) return rhs->isAtRipupLimit();
if ( (_flags & TrackCost::DiscardGlobals)
and (lhs->isOverlapGlobal() xor rhs->isOverlapGlobal()) )
return rhs->isOverlapGlobal();
if ( lhs->isHardOverlap() xor rhs->isHardOverlap() ) return rhs->isHardOverlap();
if ( lhs->_ripupCount + (int)Session::getRipupCost() < rhs->_ripupCount ) return true;
if ( lhs->_ripupCount > (int)Session::getRipupCost() + rhs->_ripupCount ) return false;
//int lhsRipupCost = (lhs->_dataState<<2) + lhs->_ripupCount;
//int rhsRipupCost = (rhs->_dataState<<2) + rhs->_ripupCount;
//if ( lhsRipupCost + (int)Session::getRipupCost() < rhsRipupCost ) return true;
//if ( lhsRipupCost > (int)Session::getRipupCost() + rhsRipupCost ) return false;
//if ( _flags & TrackCost::DiscardGlobals ) {
// if ( lhs->_longuestOverlap < rhs->_longuestOverlap ) return true;
// if ( lhs->_longuestOverlap > rhs->_longuestOverlap ) return false;
//}
if ( lhs->isOverlap() xor rhs->isOverlap() ) return rhs->isOverlap();
if ( lhs->_terminals < rhs->_terminals ) return true;
if ( lhs->_terminals > rhs->_terminals ) return false;
if (lhs->_delta != rhs->_delta) {
//cdebug_log(155,0) << "TrackCost::Compare() lhs->_delta:" << lhs->_delta << " rhs->_delta:" << rhs->_delta << endl;
//if ( not (_flags & TrackCost::IgnoreSharedLength) or (lhs->_delta > 0) or (rhs->_delta > 0) ) {
//if ( (lhs->_delta > 0) or (rhs->_delta > 0) ) {
if (lhs->_delta < rhs->_delta) return true;
if (lhs->_delta > rhs->_delta) return false;
//}
// Both delta should be negative, chose the least one.
//return lhs->_delta > rhs->_delta;
return lhs->_delta < rhs->_delta;
}
#if 0
DbU::Unit lhsMixedWeight = 0.5*lhs->_deltaPerpand;
DbU::Unit rhsMixedWeight = 0.5*rhs->_deltaPerpand;
if ( not (_flags & TrackCost::IgnoreAxisWeight) ) {
lhsMixedWeight += lhsMixedWeight;
rhsMixedWeight += rhsMixedWeight;
}
if (lhsMixedWeight < rhsMixedWeight) return true;
if (lhsMixedWeight > rhsMixedWeight) return false;
#endif
if ( not (_flags & TrackCost::IgnoreAxisWeight) ) {
if ( lhs->_axisWeight < rhs->_axisWeight ) return true;
if ( lhs->_axisWeight > rhs->_axisWeight ) return false;
}
if ( lhs->_deltaPerpand < rhs->_deltaPerpand ) return true;
if ( lhs->_deltaPerpand > rhs->_deltaPerpand ) return false;
if ( lhs->_distanceToFixed > rhs->_distanceToFixed ) return true;
if ( lhs->_distanceToFixed < rhs->_distanceToFixed ) return false;
return lhs->getTrack(0)->getAxis() < rhs->getTrack(0)->getAxis();
}
bool TrackCost::CompareByDelta::operator() ( const TrackCost* lhs, const TrackCost* rhs )
{
return lhs->getDelta() < rhs->getDelta();
}
Net* TrackCost::getNet1 () const { return (_segment1) ? _segment1->getNet() : NULL; }
Net* TrackCost::getNet2 () const { return (_segment2) ? _segment2->getNet() : NULL; }
size_t TrackCost::getBegin ( size_t i, uint32_t flags ) const
{
if (i >= _span) return Track::npos;
return std::get<1>( _tracks[i + ((flags & Symmetric) ? _span : 0)] );
}
size_t TrackCost::getEnd ( size_t i, uint32_t flags ) const
{
if (i >= _span) return Track::npos;
return std::get<2>( _tracks[i + ((flags & Symmetric) ? _span : 0)] );
}
void TrackCost::consolidate ()
{
if ( not isInfinite() and not isHardOverlap() ) {
cdebug_log(159,0) << "TrackCost::consolidate() " << _delta << " - " << _deltaShared << endl;
//_deltaPerpand += - (_deltaShared << 1);
_delta -= _deltaShared;
//if (_delta > 0) _delta -= _deltaShared;
//else _delta += _deltaShared;
}
}
void TrackCost::setDistanceToFixed ()
{
if (_flags & Analog) return;
// This is the GCell side (it is *one* cell height from the gauge).
DbU::Unit cellHeight = Session::getSliceHeight();
cdebug_log(159,0) << "TrackCost::setDistanceToFixed() begin:" << getBegin(0) << endl;
TrackElement* neighbor;
if (getBegin(0) != Track::npos) {
neighbor = getTrack(0)->getSegment(getBegin(0));
if ( neighbor and (neighbor->getNet() != getNet()) ) {
DbU::Unit distance = getInterval().getVMin() - neighbor->getTargetU();
if ( distance < cellHeight )
_distanceToFixed = distance;
}
// if ( neighbor and neighbor->isFixed() ) {
// if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
// _distanceToFixed += _interval.getVMin() - neighbor->getTargetU();
// }
}
if (getEnd(0) != Track::npos) {
neighbor = getTrack(0)->getSegment(getEnd(0));
if ( neighbor and (neighbor->getNet() != getNet()) ) {
DbU::Unit distance = neighbor->getSourceU() - getInterval().getVMax();
if ( _distanceToFixed == 2*cellHeight ) _distanceToFixed = 0;
if ( distance < cellHeight )
_distanceToFixed += distance;
}
// if ( neighbor and neighbor->isFixed() ) {
// if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
// _distanceToFixed += neighbor->getSourceU() - _interval.getVMax();
// }
}
}
string TrackCost::_getString () const
{
string s = "<" + _getTypeName();
s += " @" + DbU::getValueString(getRefCandidateAxis());
s += " " + getString(getTrack(0)->getLayer()->getName());
s += " " + getString(_dataState);
s += "+" + getString(_ripupCount);
s += ":" + getString((_dataState<<2)+_ripupCount);
s += " " + string ( (isInfinite() )?"I":"-" );
s += string ( (isBlockage() )?"b":"-" );
s += string ( (isFixed() )?"f":"-" );
s += string ( (isHardOverlap() )?"h":"-" );
s += string ( (isOverlap() )?"o":"-" );
s += string ( (isOverlapGlobal() )?"g":"-" );
s += string ( (isGlobalEnclosed())?"e":"-" );
s += string ( (isAtRipupLimit ())?"R":"-" );
s += string ( (isAnalog ())?"a":"-" );
s += string ( (isShortNet ())?"N":"-" );
s += " t:" + getString(_terminals);
s += "/d:" + /*DbU::getValueString(_delta)*/ getString(_delta);
s += "-" + /*DbU::getValueString(_deltaShared)*/ getString(_deltaShared);
s += "/aw:" + DbU::getValueString(_axisWeight);
s += "/dp:" + DbU::getValueString(_deltaPerpand);
s += "/df:" + DbU::getValueString(_distanceToFixed);
s += "/ov:" + DbU::getValueString(_longuestOverlap);
s += " " + getString(_dataState);
s += ">";
return s;
}
Record* TrackCost::_getRecord () const
{
Record* record = new Record ( _getString() );
record->add( getSlot ( "_flags" , _flags ) );
record->add( getSlot ( "_tracks" , _tracks ) );
record->add( getSlot ( "_interval1" , &_interval1 ) );
record->add( getSlot ( "_interval2" , &_interval2 ) );
record->add( getSlot ( "_terminals" , _terminals ) );
record->add( DbU::getValueSlot( "_delta" , &_delta ) );
record->add( DbU::getValueSlot( "_deltaShared" , &_deltaShared ) );
record->add( DbU::getValueSlot( "_deltaPerpand" , &_deltaPerpand ) );
record->add( DbU::getValueSlot( "_axisWeight" , &_axisWeight ) );
record->add( DbU::getValueSlot( "_distanceToFixed", &_distanceToFixed ) );
record->add( DbU::getValueSlot( "_longuestOverlap", &_longuestOverlap ) );
return record;
}
} // Katana namespace.