Added a new post-routing stage "realign" in Katana.

When a segment is placed only once (which is to say it is nerver ripped
up) it can sometimes end-up in a non-optimal place. We now add a stage
in Katana where each segment is "re-placed" in order to maximise
alignment on it's neighbor. This is a new stage added to both
RoutingEvent and NegociateWidow. Segments are replaced *only* in free
space, they will not ripup *other* segments, except for their own
perpandiculars. We exclude from re-placement globals (unlikely to move)
and segment that have reduced perpandiculars which *must* not be elongated
and potentially raised.
  Add a new katana setting to enable/disable the realign stage (enabled
by default:
    - "katana.runRealignStage" ( = True )
This commit is contained in:
Jean-Paul Chaput 2021-04-08 15:10:14 +02:00
parent 4b6da7bde9
commit 2a1f014491
15 changed files with 126 additions and 35 deletions

View File

@ -53,6 +53,7 @@ namespace Katana {
, _bloatOverloadAdd (Cfg::getParamInt ("katana.bloatOverloadAdd" , 4)->asInt())
, _flags (0)
, _profileEventCosts (Cfg::getParamBool("katana.profileEventCosts" ,false )->asBool())
, _runRealignStage (Cfg::getParamBool("katana.runRealignStage" ,true )->asBool())
{
_ripupLimits[StrapRipupLimit] = Cfg::getParamInt("katana.strapRipupLimit" ,16)->asInt();
_ripupLimits[LocalRipupLimit] = Cfg::getParamInt("katana.localRipupLimit" , 7)->asInt();
@ -100,6 +101,7 @@ namespace Katana {
, _bloatOverloadAdd (other._bloatOverloadAdd)
, _flags (other._flags)
, _profileEventCosts (other._profileEventCosts)
, _runRealignStage (other._runRealignStage)
{
_ripupLimits[StrapRipupLimit] = other._ripupLimits[StrapRipupLimit];
_ripupLimits[LocalRipupLimit] = other._ripupLimits[LocalRipupLimit];

View File

@ -681,6 +681,43 @@ namespace Katana {
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
}
if (_katana->getConfiguration()->runRealignStage()) {
cmess1 << " o Realign Stage." << endl;
cdebug_log(159,0) << "Loadind realign queue." << endl;
RoutingEvent::setStage( RoutingEvent::Realign );
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 );
}
}
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
//}

View File

@ -377,6 +377,8 @@ namespace Katana {
_segment->getDataNegociate()->setState( DataNegociate::Repair );
} else if (getStage() == RoutingEvent::Pack) {
fork->setMode( RoutingEvent::Pack );
} else if (getStage() == RoutingEvent::Realign) {
fork->setMode( RoutingEvent::Realign );
}
queue.repush( fork );
@ -470,6 +472,7 @@ namespace Katana {
case Negociate: _processNegociate( queue, history ); break;
case Pack: _processPack ( queue, history ); break;
case Repair: _processRepair ( queue, history ); break;
case Realign: _processRealign ( queue, history ); break;
default:
cerr << Bug( "RoutingEvent::process() - Unknown mode value:%d.", _mode ) << endl;
break;
@ -661,6 +664,31 @@ namespace Katana {
}
void RoutingEvent::_processRealign ( RoutingEventQueue& queue, RoutingEventHistory& history )
{
cdebug_log(159,0) << "* Mode:Realign." << endl;
SegmentFsm fsm ( this, queue, history );
if (fsm.getState() == SegmentFsm::MissingData ) return;
if (fsm.getState() == SegmentFsm::EmptyTrackList) return;
if (fsm.isSymmetric()) return;
cdebug_log(159,0) << "| Candidate Tracks:" << endl;
size_t itrack = 0;
for ( itrack = 0 ; itrack < fsm.getCosts().size() ; itrack++ )
cdebug_log(159,0) << "| " << itrack << ":" << fsm.getCost(itrack) << endl;
if ( fsm.getCosts().size()
and fsm.getCost(0)->isFree()
and (fsm.getCost(0)->getTrack() != getSegment()->getTrack())) {
cdebug_log(159,0) << "Insert in free space." << endl;
fsm.moveToTrack( 0 );
fsm.doActions();
queue.commit();
}
}
void RoutingEvent::revalidate ()
{
if (_segment->isNonPref()) { _revalidateNonPref(); return; }

View File

@ -636,7 +636,8 @@ namespace Katana {
and (_data1->getState() < DataNegociate::Minimize)
and (_data1->getRipupCount() < 5))
? TrackCost::DiscardGlobals : 0;
flags |= (RoutingEvent::getStage() == RoutingEvent::Repair) ? TrackCost::IgnoreSharedLength : 0;
flags |= (RoutingEvent::getStage() == RoutingEvent::Repair ) ? TrackCost::IgnoreSharedLength : 0;
flags |= (RoutingEvent::getStage() == RoutingEvent::Realign) ? TrackCost::IgnoreTerminals : 0;
if (flags & TrackCost::DiscardGlobals) {
cdebug_log(159,0) << "TrackCost::Compare() - DiscardGlobals" << endl;

View File

@ -404,13 +404,13 @@ namespace Katana {
}
void Session::_addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
void Session::_addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis, bool check )
{
cdebug_log(159,0) << "addInsertEvent() " << segment
<< "\n @" << DbU::getValueString(axis)
<< " " << track << endl;
if ( segment->getTrack() != NULL ) {
if ( check and (segment->getTrack() != NULL) ) {
cerr << Bug("Session::addInsertEvent(): Segment already in Track."
"\n %s."
"\n to %s."
@ -460,8 +460,7 @@ namespace Katana {
} else {
_addRemoveEvent( segment );
}
_addInsertEvent( segment, track, axis );
_addInsertEvent( segment, track, axis, false );
}

View File

@ -374,11 +374,11 @@ namespace Katana {
Interval freeInterval = getFreeInterval( interval.getCenter(), cost.getNet() );
if (not freeInterval.contains(interval)) {
getOverlapBounds( cost.getInterval(), begin, end );
cost.setFreeLength( 0 );
} else {
cost.setFreeLength( freeInterval.getSize() );
}
getOverlapBounds( cost.getInterval(), begin, end );
cost.setTrack( const_cast<Track*>(this), begin, end );
cdebug_log(155,1) << "addOverlapCost() @" << DbU::getValueString(_axis)
@ -386,6 +386,7 @@ namespace Katana {
<< ":" << DbU::getValueString(interval.getVMax())
<< "] <-> [" << begin << ":" << end << "]"
<< endl;
cdebug_log(155,0) << "initial:" << &cost << endl;
cdebug_log(155,0) << "freeInterval [" << DbU::getValueString(freeInterval.getVMin())
<< ":" << DbU::getValueString(freeInterval.getVMax()) << "]"
<< endl;
@ -409,7 +410,20 @@ namespace Katana {
}
if (begin == npos) {
if (not _segments.empty()
and (_segments.back()->getNet() == cost.getNet())
and (cost.getRefElement()->getAxis() != getAxis())
) {
Interval overlap = interval.getIntersection( _segments.back()->getCanonicalInterval() );
cdebug_log(155,0) << "overlap:" << overlap
<< " size:" << DbU::getValueString(overlap.getSize()) << endl;
if (overlap.getSize() > 0) {
cdebug_log(155,0) << "Same net overlap, increase delta shared." << endl;
cost.incDeltaShared ( overlap.getSize() );
}
}
cdebug_log(155,0) << " begin == npos (after last TrackElement)." << endl;
cdebug_log(155,0) << " current:" << &cost << endl;
cdebug_tabw(155,-1);
return cost;
}
@ -420,7 +434,9 @@ namespace Katana {
<< " size:" << DbU::getValueString(overlap.getSize()) << endl;
if (overlap.getSize() == 0) continue;
if (_segments[begin]->getNet() == cost.getNet()) {
if ( (_segments[begin]->getNet() == cost.getNet())
and ((cost.getRefElement()->getAxis() != getAxis())
or not _segments[begin]->isNonPref() ) ) {
cdebug_log(155,0) << "Same net overlap, increase delta shared." << endl;
cost.incDeltaShared ( overlap.getSize() );
}

View File

@ -132,8 +132,10 @@ namespace Katana {
if ( lhs->isOverlap() xor rhs->isOverlap() ) return rhs->isOverlap();
if ( lhs->_terminals < rhs->_terminals ) return true;
if ( lhs->_terminals > rhs->_terminals ) return false;
if (not (_flags & TrackCost::IgnoreTerminals)) {
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;
@ -203,7 +205,8 @@ namespace Katana {
void TrackCost::consolidate ()
{
if ( not isInfinite() and not isHardOverlap() ) {
cdebug_log(159,0) << "TrackCost::consolidate() " << _delta << " - " << _deltaShared << endl;
cdebug_log(159,0) << "TrackCost::consolidate() " << DbU::getValueString(_delta)
<< " - " << DbU::getValueString(_deltaShared) << endl;
//_deltaPerpand += - (_deltaShared << 1);
_delta -= _deltaShared;
//if (_delta > 0) _delta -= _deltaShared;
@ -270,8 +273,8 @@ namespace Katana {
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 += "/d:" + /*DbU::getValueString(_delta)*/ DbU::getValueString(_delta);
s += "-" + /*DbU::getValueString(_deltaShared)*/ DbU::getValueString(_deltaShared);
s += "/aw:" + DbU::getValueString(_axisWeight);
s += "/dp:" + DbU::getValueString(_deltaPerpand);
s += "/df:" + DbU::getValueString(_distanceToFixed);

View File

@ -161,6 +161,7 @@ namespace Katana {
bool TrackElement::canDogleg () { return false; };
bool TrackElement::canDogleg ( Interval ) { return false; };
bool TrackElement::canDogleg ( Anabatic::GCell*, Flags ) { return false; };
bool TrackElement::canRealign () const { return false; };
// Accessors.
unsigned long TrackElement::getId () const { return 0; }
unsigned long TrackElement::getFreedomDegree () const { return 0; }

View File

@ -601,6 +601,16 @@ namespace Katana {
float TrackSegment::getMaxUnderDensity ( Flags flags ) const
{ return _base->getMaxUnderDensity( flags ); }
bool TrackSegment::canRealign () const
{
if (isGlobal() or isNonPref() or isReduced()) return false;
for ( TrackElement* perpandicular : const_cast<TrackSegment*>(this)->getPerpandiculars() ) {
if (perpandicular->isReduced()) return false;
}
return true;
}
bool TrackSegment::canPivotUp ( float reserve, Flags flags ) const

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef KATANA_CONFIGURATION_H
#define KATANA_CONFIGURATION_H
#pragma once
#include <functional>
#include "anabatic/Configuration.h"
#include "katana/Constants.h"
@ -67,6 +65,7 @@ namespace Katana {
inline bool useGlobalEstimate () const;
inline bool useStaticBloatProfile () const;
inline bool profileEventCosts () const;
inline bool runRealignStage () const;
// Methods.
inline Anabatic::Configuration* base ();
inline const Anabatic::Configuration* base () const;
@ -94,6 +93,7 @@ namespace Katana {
inline void setFlags ( unsigned int );
inline void unsetFlags ( unsigned int );
inline void setProfileEventCosts ( bool );
inline void setRunRealignStage ( bool );
virtual void print ( Cell* ) const;
virtual Record* _getRecord () const;
virtual string _getString () const;
@ -114,6 +114,7 @@ namespace Katana {
uint32_t _bloatOverloadAdd;
unsigned int _flags;
bool _profileEventCosts;
bool _runRealignStage;
private:
Configuration ( const Configuration& other );
Configuration& operator= ( const Configuration& );
@ -142,9 +143,11 @@ namespace Katana {
inline bool Configuration::useGlobalEstimate () const { return _flags & UseGlobalEstimate; }
inline bool Configuration::useStaticBloatProfile () const { return _flags & UseStaticBloatProfile; }
inline bool Configuration::profileEventCosts () const { return _profileEventCosts; }
inline bool Configuration::runRealignStage () const { return _runRealignStage; }
inline void Configuration::setFlags ( unsigned int flags ) { _flags |= flags; }
inline void Configuration::unsetFlags ( unsigned int flags ) { _flags &= ~flags; }
inline void Configuration::setProfileEventCosts ( bool state ) { _profileEventCosts = state; }
inline void Configuration::setRunRealignStage ( bool state ) { _runRealignStage = state; }
@ -152,6 +155,3 @@ namespace Katana {
INSPECTOR_P_SUPPORT(Katana::Configuration);
#endif // KATANA_CONFIGURATION_H

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef KATANA_ROUTING_EVENT_H
#define KATANA_ROUTING_EVENT_H
#pragma once
#include <set>
#include <vector>
#include <cstdlib>
@ -94,7 +92,7 @@ namespace Katana {
friend class Compare;
public:
enum Mode { Negociate=1, Pack=2, Repair=3 };
enum Mode { Negociate=1, Pack=2, Repair=3, Realign=4 };
public:
static uint32_t getStage ();
@ -163,6 +161,7 @@ namespace Katana {
void _processNegociate ( RoutingEventQueue&, RoutingEventHistory& );
void _processPack ( RoutingEventQueue&, RoutingEventHistory& );
void _processRepair ( RoutingEventQueue&, RoutingEventHistory& );
void _processRealign ( RoutingEventQueue&, RoutingEventHistory& );
Record* _getRecord () const;
string _getString () const;
string _getTypeName () const;
@ -287,6 +286,3 @@ namespace Katana {
INSPECTOR_P_SUPPORT(Katana::RoutingEvent);
#endif // KATANA_ROUTING_EVENT_H

View File

@ -80,7 +80,7 @@ namespace Katana {
inline static Interval& toAxisInterval ( Interval&, size_t depth );
inline static void addIndirectInvalid ( TrackElement* );
inline static void addInsertEvent ( TrackMarker* , Track* );
inline static void addInsertEvent ( TrackElement* , Track*, DbU::Unit axis );
inline static void addInsertEvent ( TrackElement* , Track*, DbU::Unit axis, bool check=true );
inline static void addRemoveEvent ( TrackElement* );
inline static void addMoveEvent ( TrackElement* , Track*, DbU::Unit axis );
inline static void addSortEvent ( Track*, bool forced=false );
@ -107,7 +107,7 @@ namespace Katana {
_getIndirectInvalids ();
inline void _addIndirectInvalid ( TrackElement* );
void _addInsertEvent ( TrackMarker* , Track* );
void _addInsertEvent ( TrackElement* , Track*, DbU::Unit axis );
void _addInsertEvent ( TrackElement* , Track*, DbU::Unit axis, bool check );
void _addRemoveEvent ( TrackElement* );
void _addMoveEvent ( TrackElement* , Track*, DbU::Unit axis );
void _addSortEvent ( Track*, bool forced );
@ -191,8 +191,8 @@ namespace Katana {
inline void Session::addInsertEvent ( TrackMarker* marker, Track* track )
{ get("addInsertEvent(TrackMarker*)")->_addInsertEvent(marker,track); }
inline void Session::addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
{ get("addInsertEvent(TrackElement*)")->_addInsertEvent(segment,track,axis); }
inline void Session::addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis, bool check )
{ get("addInsertEvent(TrackElement*)")->_addInsertEvent(segment,track,axis,check); }
inline void Session::addRemoveEvent ( TrackElement* segment )
{ get("addRemoveEvent()")->_addRemoveEvent(segment); }

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef KATANA_TRACK_COST_H
#define KATANA_TRACK_COST_H
#pragma once
#include <string>
#include <tuple>
#include "hurricane/Interval.h"
@ -61,6 +59,7 @@ namespace Katana {
, OverlapGlobal = (1 << 16)
, GlobalEnclosed = (1 << 17)
, AtRipupLimit = (1 << 18)
, IgnoreTerminals = (1 << 19)
, MergeMask = ForGlobal |Blockage|Fixed |Infinite
|HardOverlap |Overlap |RightOverlap|LeftOverlap|OverlapGlobal
|GlobalEnclosed |AtRipupLimit
@ -326,6 +325,3 @@ namespace Katana {
INSPECTOR_P_SUPPORT(Katana::TrackCost);
#endif // KATANA_TRACK_COST_H

View File

@ -142,6 +142,7 @@ namespace Katana {
virtual bool canDogleg ();
virtual bool canDogleg ( Interval );
virtual bool canDogleg ( Anabatic::GCell*, Flags flags=0 );
virtual bool canRealign () const;
// Accessors
inline Observer<TrackElement>* getObserver ();
virtual unsigned long getId () const;

View File

@ -93,6 +93,7 @@ namespace Katana {
virtual bool canPivotDown ( float reserve, Flags ) const;
virtual bool canMoveUp ( float reserve, Flags ) const;
virtual bool canSlacken () const;
virtual bool canRealign () const;
virtual float getMaxUnderDensity ( Flags ) const;
virtual unsigned long getId () const;
virtual Flags getDirection () const;