2013-12-03 18:59:29 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
2018-01-06 10:55:44 -06:00
|
|
|
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
2013-12-03 18:59:29 -06:00
|
|
|
//
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
// | 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 |
|
2016-03-06 05:36:18 -06:00
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
2013-12-03 18:59:29 -06:00
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./SegmentFsm.cpp" |
|
|
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
|
|
#include "kite/TrackElement.h"
|
|
|
|
#include "kite/Tracks.h"
|
|
|
|
#include "kite/RoutingPlane.h"
|
|
|
|
#include "kite/DataNegociate.h"
|
|
|
|
#include "kite/RoutingEvent.h"
|
|
|
|
#include "kite/RoutingEventQueue.h"
|
|
|
|
#include "kite/RoutingEventHistory.h"
|
|
|
|
#include "kite/Manipulator.h"
|
|
|
|
#include "kite/SegmentFsm.h"
|
|
|
|
#include "kite/KiteEngine.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Hurricane;
|
|
|
|
using namespace Kite;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Cs1Candidate".
|
|
|
|
|
|
|
|
class Cs1Candidate {
|
|
|
|
public:
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
inline Cs1Candidate ( Track* track=NULL, DbU::Unit ppitch=0 );
|
2013-12-03 18:59:29 -06:00
|
|
|
inline Track* getTrack () const;
|
|
|
|
inline size_t getBegin () const;
|
|
|
|
inline size_t getEnd () const;
|
|
|
|
inline size_t getLength () const;
|
|
|
|
inline Interval getConflict ( size_t );
|
|
|
|
inline Interval getLongestConflict () const;
|
|
|
|
inline DbU::Unit getBreakPos () const;
|
|
|
|
inline DbU::Unit getConflictLength () const;
|
|
|
|
inline void setBegin ( size_t );
|
|
|
|
inline void setEnd ( size_t );
|
|
|
|
inline void addConflict ( const Interval& );
|
|
|
|
void consolidate ();
|
|
|
|
public:
|
|
|
|
friend inline bool operator< ( const Cs1Candidate&, const Cs1Candidate& );
|
|
|
|
private:
|
|
|
|
Track* _track;
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
DbU::Unit _ppitch;
|
2013-12-03 18:59:29 -06:00
|
|
|
size_t _begin;
|
|
|
|
size_t _end;
|
|
|
|
vector<Interval> _conflicts;
|
|
|
|
Interval _longestConflict;
|
|
|
|
DbU::Unit _breakPos;
|
|
|
|
DbU::Unit _conflictLength;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
inline Cs1Candidate::Cs1Candidate ( Track* track, DbU::Unit ppitch )
|
2013-12-03 18:59:29 -06:00
|
|
|
: _track (track)
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
, _ppitch (ppitch)
|
2013-12-03 18:59:29 -06:00
|
|
|
, _begin (0)
|
|
|
|
, _end (0)
|
|
|
|
, _conflicts ()
|
|
|
|
, _longestConflict()
|
|
|
|
, _breakPos (0)
|
|
|
|
, _conflictLength (0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
inline Track* Cs1Candidate::getTrack () const { return _track; }
|
|
|
|
inline size_t Cs1Candidate::getBegin () const { return _begin; }
|
|
|
|
inline size_t Cs1Candidate::getEnd () const { return _end; }
|
|
|
|
inline size_t Cs1Candidate::getLength () const { return _conflicts.size(); }
|
|
|
|
inline Interval Cs1Candidate::getLongestConflict () const { return _longestConflict; }
|
|
|
|
inline DbU::Unit Cs1Candidate::getBreakPos () const { return _breakPos; }
|
|
|
|
inline void Cs1Candidate::setBegin ( size_t i ) { _begin=i; }
|
|
|
|
inline void Cs1Candidate::setEnd ( size_t i ) { _end=i; }
|
|
|
|
|
|
|
|
inline void Cs1Candidate::addConflict ( const Interval& conflict )
|
|
|
|
{
|
|
|
|
_conflicts.push_back(conflict);
|
|
|
|
_conflictLength += conflict.getSize();
|
|
|
|
|
|
|
|
if (conflict.getSize() > _longestConflict.getSize())
|
|
|
|
_longestConflict = conflict;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Interval Cs1Candidate::getConflict ( size_t i )
|
|
|
|
{
|
|
|
|
if (i >= _conflicts.size()) return Interval();
|
|
|
|
return _conflicts[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator< ( const Cs1Candidate& lhs, const Cs1Candidate& rhs )
|
|
|
|
{
|
|
|
|
DbU::Unit delta = lhs._longestConflict.getSize() - rhs._longestConflict.getSize();
|
|
|
|
if (delta < 0) return true;
|
|
|
|
if (delta > 0) return false;
|
|
|
|
|
|
|
|
return lhs._conflictLength < rhs._conflictLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Cs1Candidate::consolidate ()
|
|
|
|
{
|
|
|
|
if (_conflicts.size() > 0) {
|
|
|
|
DbU::Unit halfConflict = 0;
|
|
|
|
size_t i = 0;
|
|
|
|
for ( ; i<_conflicts.size()-1 ; ++i ) {
|
|
|
|
halfConflict += _conflicts[i].getSize();
|
|
|
|
if (halfConflict > _conflictLength/2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ugly: hard-coded pitch.
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
_breakPos = _conflicts[i].getVMin() - _ppitch;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "UnionItervals".
|
|
|
|
|
|
|
|
class UnionIntervals {
|
|
|
|
public:
|
|
|
|
inline UnionIntervals ();
|
|
|
|
void addInterval ( Interval& );
|
|
|
|
inline size_t size () const;
|
|
|
|
inline bool empty () const;
|
|
|
|
inline list<Interval>::const_iterator begin () const;
|
|
|
|
inline list<Interval>::const_iterator end () const;
|
|
|
|
inline DbU::Unit getVMin () const;
|
|
|
|
inline DbU::Unit getVMax () const;
|
|
|
|
string _getString ();
|
|
|
|
private:
|
|
|
|
list<Interval> _intervals;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
inline UnionIntervals::UnionIntervals () : _intervals() { }
|
|
|
|
inline list<Interval>::const_iterator UnionIntervals::begin () const { return _intervals.begin(); }
|
|
|
|
inline list<Interval>::const_iterator UnionIntervals::end () const { return _intervals.end(); }
|
|
|
|
inline size_t UnionIntervals::size () const { return _intervals.size(); }
|
|
|
|
inline bool UnionIntervals::empty () const { return _intervals.empty(); }
|
|
|
|
inline DbU::Unit UnionIntervals::getVMin () const { return (empty()) ? DbU::Max : (*begin()).getVMin(); }
|
|
|
|
inline DbU::Unit UnionIntervals::getVMax () const { return (empty()) ? DbU::Min : (*begin()).getVMax(); }
|
|
|
|
|
|
|
|
|
|
|
|
void UnionIntervals::addInterval ( Interval& interval )
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "UnionInterval::addInterval() - " << interval << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
list<Interval>::iterator iintv = _intervals.begin ();
|
|
|
|
|
|
|
|
bool merged = false;
|
|
|
|
while ( iintv != _intervals.end() ) {
|
|
|
|
if (not merged) {
|
|
|
|
if (interval.getVMax() < (*iintv).getVMin()) { _intervals.insert( iintv, interval ); return; }
|
|
|
|
if (interval.getVMin() > (*iintv).getVMax()) { ++iintv; continue; }
|
|
|
|
|
|
|
|
merged = true;
|
|
|
|
interval = (*iintv).merge( interval );
|
|
|
|
++iintv;
|
|
|
|
} else {
|
|
|
|
if ((*iintv).intersect( interval )) {
|
|
|
|
interval = (*iintv).merge( interval );
|
|
|
|
iintv = _intervals.erase( iintv );
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not merged) _intervals.push_back( interval );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string UnionIntervals::_getString ()
|
|
|
|
{
|
|
|
|
ostringstream s;
|
|
|
|
|
|
|
|
list<Interval>::iterator iintv = _intervals.begin();
|
|
|
|
for ( ; iintv != _intervals.end() ; ++iintv ) {
|
|
|
|
s << " [" << DbU::getValueString((*iintv).getVMin())
|
|
|
|
<< ":" << DbU::getValueString((*iintv).getVMax()) << "]";
|
|
|
|
}
|
|
|
|
return s.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "RipupHistory".
|
|
|
|
|
|
|
|
class RipupHistory {
|
|
|
|
public:
|
|
|
|
RipupHistory ( RoutingEvent* );
|
|
|
|
inline bool isDislodger ( RoutingEvent* ) const;
|
|
|
|
inline size_t size () const;
|
|
|
|
inline size_t getDislodgersCount () const;
|
|
|
|
void addAxis ( DbU::Unit );
|
|
|
|
void addAxis ( RoutingEvent* );
|
|
|
|
bool hasAxis ( DbU::Unit ) const;
|
|
|
|
UnionIntervals* getUnionIntervals ( DbU::Unit );
|
|
|
|
void addDislodger ( RoutingEvent* );
|
|
|
|
void addDislodger ( TrackElement* );
|
|
|
|
void print ( ostream& );
|
|
|
|
private:
|
|
|
|
RoutingEvent* _masterEvent;
|
|
|
|
map<DbU::Unit,UnionIntervals> _dislodgers;
|
|
|
|
size_t _dislodgersCount;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
RipupHistory::RipupHistory ( RoutingEvent* event )
|
|
|
|
: _masterEvent (event)
|
|
|
|
, _dislodgers ()
|
|
|
|
, _dislodgersCount(0)
|
|
|
|
{
|
|
|
|
const Interval& perpandicular = _masterEvent->getPerpandicularFree();
|
|
|
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(_masterEvent->getSegment()->getLayer());
|
|
|
|
Track* track;
|
|
|
|
|
|
|
|
if (not perpandicular.isEmpty()) {
|
|
|
|
track = plane->getTrackByPosition(perpandicular.getVMin());
|
|
|
|
|
|
|
|
if (track and (track->getAxis() < perpandicular.getVMin())) track = track->getNextTrack();
|
|
|
|
for ( ; track && (track->getAxis() <= perpandicular.getVMax())
|
|
|
|
; track = track->getNextTrack() )
|
|
|
|
addAxis( track->getAxis() );
|
|
|
|
}
|
|
|
|
|
|
|
|
track = plane->getTrackByPosition(_masterEvent->getSegment()->getAxis());
|
|
|
|
if (track) {
|
|
|
|
size_t begin = Track::npos;
|
|
|
|
size_t end = Track::npos;
|
|
|
|
Interval interval = _masterEvent->getSegment()->getCanonicalInterval();
|
|
|
|
track->getOverlapBounds( interval, begin, end );
|
|
|
|
|
|
|
|
if (begin != Track::npos) {
|
|
|
|
for ( ; begin < end ; ++begin ) {
|
|
|
|
TrackElement* other = track->getSegment(begin);
|
|
|
|
if (other->getNet() == _masterEvent->getSegment()->getNet() ) continue;
|
|
|
|
if (not interval.intersect(other->getCanonicalInterval())) continue;
|
|
|
|
|
|
|
|
addDislodger( other );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool RipupHistory::isDislodger ( RoutingEvent* event ) const { return hasAxis(event->getSegment()->getAxis()); }
|
|
|
|
inline size_t RipupHistory::size () const { return _dislodgers.size(); }
|
|
|
|
inline size_t RipupHistory::getDislodgersCount () const { return _dislodgersCount; }
|
|
|
|
|
|
|
|
|
|
|
|
void RipupHistory::addAxis ( DbU::Unit axis )
|
|
|
|
{
|
|
|
|
if (hasAxis(axis)) return;
|
|
|
|
_dislodgers.insert( make_pair(axis,UnionIntervals()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RipupHistory::addAxis ( RoutingEvent* event )
|
|
|
|
{ addAxis( event->getAxisHistory() ); }
|
|
|
|
|
|
|
|
|
|
|
|
bool RipupHistory::hasAxis ( DbU::Unit axis ) const
|
|
|
|
{ return _dislodgers.find(axis) != _dislodgers.end(); }
|
|
|
|
|
|
|
|
|
|
|
|
UnionIntervals* RipupHistory::getUnionIntervals ( DbU::Unit axis )
|
|
|
|
{
|
|
|
|
map<DbU::Unit,UnionIntervals>::iterator iunion = _dislodgers.find ( axis );
|
|
|
|
if (iunion == _dislodgers.end()) return NULL;
|
|
|
|
|
|
|
|
return &(iunion->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RipupHistory::addDislodger ( RoutingEvent* event )
|
|
|
|
{
|
|
|
|
if (event->getSegment() == _masterEvent->getSegment()) return;
|
|
|
|
if (event->getSegment()->getLayer() != _masterEvent->getSegment()->getLayer()) return;
|
|
|
|
|
|
|
|
UnionIntervals* intervals = getUnionIntervals( event->getAxisHistory() );
|
|
|
|
if (not intervals) return;
|
|
|
|
|
|
|
|
Interval canonical = event->getSegment()->getCanonicalInterval();
|
|
|
|
intervals->addInterval( canonical );
|
|
|
|
|
|
|
|
++_dislodgersCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RipupHistory::addDislodger ( TrackElement* segment )
|
|
|
|
{
|
|
|
|
if (_masterEvent->getSegment()->getNet() == segment->getNet()) return;
|
|
|
|
|
|
|
|
UnionIntervals* intervals = getUnionIntervals( segment->getAxis() );
|
|
|
|
if (not intervals) return;
|
|
|
|
|
|
|
|
Interval canonical = segment->getCanonicalInterval();
|
|
|
|
intervals->addInterval( canonical );
|
|
|
|
|
|
|
|
++_dislodgersCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void RipupHistory::print ( ostream& o )
|
|
|
|
{
|
|
|
|
o << "[HISTORY] " << _masterEvent << endl;
|
|
|
|
|
|
|
|
map<DbU::Unit,UnionIntervals>::iterator iunion = _dislodgers.begin();
|
|
|
|
for ( ; iunion != _dislodgers.end() ; ++iunion )
|
|
|
|
o << " @" << DbU::getValueString(iunion->first)
|
|
|
|
<< " " << (iunion->second)._getString() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Anonymous namespace.
|
|
|
|
|
|
|
|
|
|
|
|
namespace Kite {
|
|
|
|
|
|
|
|
using std::sort;
|
|
|
|
using Hurricane::tab;
|
|
|
|
using Hurricane::DebugSession;
|
|
|
|
using Hurricane::Bug;
|
|
|
|
using Hurricane::ForEachIterator;
|
|
|
|
using Katabatic::KbHalfSlacken;
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "SegmentAction".
|
|
|
|
|
|
|
|
SegmentAction::SegmentAction ( TrackElement* segment
|
|
|
|
, unsigned int type
|
|
|
|
, DbU::Unit axisHint
|
|
|
|
, unsigned int toState
|
|
|
|
)
|
|
|
|
: _segment (segment)
|
|
|
|
, _type (type)
|
|
|
|
, _axisHint(axisHint)
|
|
|
|
, _toState (toState)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentAction::doAction ( RoutingEventQueue& queue )
|
|
|
|
{
|
|
|
|
// Note:
|
|
|
|
// "_immediate" ripup flags was associated with "perpandicular", as they
|
|
|
|
// must be re-inserted *before* any parallel. Must look to solve the redundancy.
|
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
DebugSession::open( _segment->getNet(), 150, 160 );
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if (_type & Perpandicular) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "* Riping Pp " << _segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "* Riping // " << _segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_segment->isFixed()) { DebugSession::close(); return true; }
|
|
|
|
|
|
|
|
DataNegociate* data = _segment->getDataNegociate();
|
|
|
|
if (data == NULL) { DebugSession::close(); return true; }
|
|
|
|
|
|
|
|
if (_type & ResetRipup) data->resetRipupCount();
|
|
|
|
|
|
|
|
if (_type & ToState) {
|
|
|
|
data->setState ( _toState );
|
|
|
|
data->setRipupCount( Session::getKiteEngine()->getRipupLimit(_segment) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_segment->getTrack()) Session::addRemoveEvent( _segment );
|
|
|
|
|
|
|
|
RoutingEvent* event = data->getRoutingEvent();
|
|
|
|
if (event == NULL) {
|
|
|
|
cerr << Bug( "Missing Event on %p:%s"
|
|
|
|
, _segment->base()->base(),getString(_segment).c_str() ) << endl;
|
|
|
|
DebugSession::close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (_type & AxisHint) /*and not _segment->isSlackenDogleg()*/ ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Setting Axis Hint: @" << DbU::getValueString(_axisHint) << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
event->setAxisHint( _axisHint );
|
|
|
|
}
|
|
|
|
|
|
|
|
// It is possible that this code could be disabled.
|
|
|
|
// There should be no need to move the axis of the segment to be inserted,
|
|
|
|
// it will automatically slot into the empty track, if any.
|
|
|
|
if (_type & MoveToAxis) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Moving Axis To: @" << DbU::getValueString(_axisHint) << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
_segment->setAxis( _axisHint );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_type & ToRipupLimit) {
|
|
|
|
unsigned int limit = Session::getKiteEngine()->getRipupLimit(_segment);
|
|
|
|
if (limit > data->getRipupCount())
|
|
|
|
data->setRipupCount( limit );
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int eventLevel = 0;
|
|
|
|
if (_type & EventLevel1) eventLevel = 1;
|
|
|
|
if (_type & EventLevel2) eventLevel = 2;
|
|
|
|
if (_type & EventLevel3) eventLevel = 3;
|
|
|
|
if (_type & EventLevel4) eventLevel = 4;
|
|
|
|
if (_type & EventLevel5) eventLevel = 5;
|
|
|
|
event->setRipedByLocal( _type&RipedByLocal );
|
|
|
|
|
|
|
|
RoutingEvent* fork = event->reschedule( queue, eventLevel );
|
|
|
|
|
|
|
|
if (fork) {
|
|
|
|
unsigned int mode = RoutingEvent::Repair;
|
|
|
|
if (RoutingEvent::getStage() < RoutingEvent::Repair)
|
|
|
|
mode = (_type&PackingMode) ? RoutingEvent::Pack : RoutingEvent::Negociate;
|
|
|
|
fork->setMode( mode );
|
|
|
|
}
|
|
|
|
|
|
|
|
DebugSession::close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "SegmentFsm".
|
|
|
|
|
|
|
|
|
|
|
|
SegmentFsm::SegmentFsm ( RoutingEvent* event, RoutingEventQueue& queue, RoutingEventHistory& history )
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
: _event (event)
|
|
|
|
, _queue (queue)
|
|
|
|
, _history (history)
|
|
|
|
, _state (0)
|
|
|
|
, _data (NULL)
|
|
|
|
, _constraint ()
|
|
|
|
, _optimal ()
|
|
|
|
, _costs ()
|
|
|
|
, _actions ()
|
|
|
|
, _fullBlocked(true)
|
2013-12-03 18:59:29 -06:00
|
|
|
{
|
|
|
|
TrackElement* segment = _event->getSegment();
|
|
|
|
unsigned int depth = Session::getRoutingGauge()->getLayerDepth(segment->getLayer());
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
_event->setTracksFree( 0 );
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
_data = segment->getDataNegociate();
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (not _data) {
|
2013-12-03 18:59:29 -06:00
|
|
|
_state = MissingData;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_data->update();
|
|
|
|
_event->revalidate();
|
|
|
|
|
|
|
|
_constraint = _event->getConstraints();
|
|
|
|
_optimal = _event->getOptimal();
|
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
const Interval& perpandicular = _event->getPerpandicularFree();
|
2013-12-03 18:59:29 -06:00
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Katabatic intervals:" << endl;
|
|
|
|
cdebug_log(159,0) << "* Optimal: " << _optimal << endl;
|
|
|
|
cdebug_log(159,0) << "* Constraints: " << _constraint << endl;
|
|
|
|
cdebug_log(159,0) << "* Perpandicular: " << perpandicular << endl;
|
|
|
|
cdebug_log(159,0) << "* AxisHint: " << DbU::getValueString(_event->getAxisHint()) << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (_event->getTracksNb()) {
|
|
|
|
if (_constraint.getIntersection(perpandicular).isEmpty()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Perpandicular free is too tight." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
_state = EmptyTrackList;
|
|
|
|
} else
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
_constraint.intersection( perpandicular );
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "No Track in perpandicular free." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
_state = EmptyTrackList;
|
|
|
|
}
|
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (_state == EmptyTrackList) return;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Negociate intervals:" << endl;
|
|
|
|
cdebug_log(159,0) << "* Optimal: " << _optimal << endl;
|
|
|
|
cdebug_log(159,1) << "* Constraints: " << _constraint << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
// if ( segment->isLocal() and (_data->getState() >= DataNegociate::MaximumSlack) )
|
|
|
|
// _constraint.inflate ( 0, DbU::lambda(1.0) );
|
|
|
|
|
|
|
|
bool inLocalDepth = (depth < 3);
|
|
|
|
bool isOneLocalTrack = (segment->isLocal())
|
|
|
|
and (segment->base()->getAutoSource()->getGCell()->getGlobalsCount(depth) >= 9.0);
|
|
|
|
|
|
|
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer());
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
for ( Track* track : Tracks_Range::get(plane,_constraint) ) {
|
2013-12-03 18:59:29 -06:00
|
|
|
unsigned int costflags = 0;
|
|
|
|
costflags |= (segment->isLocal() and (depth >= 3)) ? TrackCost::LocalAndTopDepth : 0;
|
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (not segment->isReduced())
|
|
|
|
_costs.push_back( track->getOverlapCost(segment,costflags) );
|
|
|
|
else
|
|
|
|
_costs.push_back( TrackCost(track,segment->getNet()) );
|
|
|
|
_costs.back().setAxisWeight ( _event->getAxisWeight(track->getAxis()) );
|
|
|
|
_costs.back().incDeltaPerpand( _data->getWiringDelta(track->getAxis()) );
|
2014-07-06 17:42:38 -05:00
|
|
|
if (segment->isGlobal()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(9000,0) << "Deter| setForGlobal() on " << track << endl;
|
2014-07-06 17:42:38 -05:00
|
|
|
_costs.back().setForGlobal();
|
|
|
|
}
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if ( inLocalDepth and (_costs.back().getDataState() == DataNegociate::MaximumSlack) )
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
_costs.back().setInfinite();
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if ( isOneLocalTrack
|
|
|
|
and _costs.back().isOverlapGlobal()
|
|
|
|
and (_costs.back().getDataState() >= DataNegociate::ConflictSolveByHistory) )
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
_costs.back().setInfinite();
|
2013-12-03 18:59:29 -06:00
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
_costs.back().consolidate();
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( _fullBlocked and (not _costs.back().isBlockage() and not _costs.back().isFixed()) )
|
|
|
|
_fullBlocked = false;
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| " << _costs.back() << ((_fullBlocked)?" FB ": " -- ") << track << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_tabw(159,-1);
|
2013-12-03 18:59:29 -06:00
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (_costs.empty()) {
|
2013-12-03 18:59:29 -06:00
|
|
|
Track* nearest = plane->getTrackByPosition(_constraint.getCenter());
|
|
|
|
|
|
|
|
if ( (nearest->getAxis() < _constraint.getVMin())
|
|
|
|
or (nearest->getAxis() > _constraint.getVMax()) ) {
|
|
|
|
//setUnimplemented ();
|
|
|
|
//cerr << "[UNIMPLEMENTED] " << segment << " no Track in constraint interval "
|
|
|
|
// << _constraint << " " << "." << endl;
|
|
|
|
} else {
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
cerr << Bug( " %s Track_Range() failed to find Tracks in %s (they exists)."
|
|
|
|
, getString(segment).c_str()
|
|
|
|
, getString(_constraint).c_str()
|
2013-12-03 18:59:29 -06:00
|
|
|
) << endl;
|
|
|
|
}
|
|
|
|
_state = EmptyTrackList;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int flags = 0;
|
|
|
|
flags |= (segment->isStrap()) ? TrackCost::IgnoreAxisWeight : 0;
|
|
|
|
flags |= (segment->isLocal()
|
|
|
|
and (_data->getState() < DataNegociate::Minimize)
|
|
|
|
and (_data->getRipupCount() < 5))
|
|
|
|
? TrackCost::DiscardGlobals : 0;
|
|
|
|
flags |= (RoutingEvent::getStage() == RoutingEvent::Repair) ? TrackCost::IgnoreSharedLength : 0;
|
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
if (flags & TrackCost::DiscardGlobals) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "TrackCost::Compare() - DiscardGlobals" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
Added support for "same layer" dogleg. Big fix for pad routing.
* Change: In Knik, in Vertex, add a "blocked" flag to signal disabled
vertexes in the grid (must not be used by the global router).
Modificate the Graph::getVertex() method so that when a vertex
is geometrically queried, if is a blocked one, return a non-blocked
neighbor. This mechanism is introduced to, at last, prevent the
global router to go *under* the pad in case of a commplete chip.
* New: In Katabatic, in AutoSegment, a new state has been added: "reduced".
A reduced segment is in the same layer as it's perpandiculars.
To be reduced, a segments has to be connected on source & target to
AutoContactTurn, both of the perpandiculars must be of the same layer
(below or above) and it's length must not exceed one pitch in the
perpandicular direction.
To reduce an AutoSegment, call ::reduce() and to revert the state,
call ::raise(). Two associated predicates are associated:
::canReduce() and ::mustRaise().
Note: No two adjacent segments can be reduced at the same time.
* Bug: In Katabatic, in GCellTopology, add a new method ::doRp_AccessPad()
to connect to the pads. Create wiring, fixed and non managed by
Katabatic, to connect the pad connector layer to the lowest routing
layers (depth 1 & 2). The former implementation was sometimes leading
to gaps (sheared contact) that *must not* occurs during the building
stage.
Remark: This bug did put under the light the fact that the initial
wiring must be created without gaps. Gaps are closed by making doglegs
on contacts. But this mechanism could only work when the database if
fully initialised (the cache is up to date). Otherwise various problems
arise, in the canonization process for example.
* New: In Katabatic, in AutoContactTerminal::getNativeConstraintBox(),
when anchored on a RoutingPad, now take account the potential rotation
of the Path's transformation. Here again, for the chip's pads.
* New: In Kite, support for reduced AutoSegment. TrackSegment associateds
to reduced AutoSegment are *not* inserted into track to become
effectively invisibles. When a segment becomes reduced, a TrackEvent
is generated to remove it. Conversely when it is raised a RoutingEvent
is created/rescheduled to insert it. All this is mostly managed inside
the Session::revalidate() method.
* New: In Kite, in KiteEngine::createGlobalGraph(), in case of a chip,
mark all global routing vertexes (Knik) that are under a pad, as blockeds.
* Bug: In Cumulus, in PadsCorona.Side.getAxis(), inversion between X and
Y coordinate of the chip size. Did not show until a non-square chip
was routed (i.e. our MIPS R3000).
* Change: In Stratus1, in st_placement.py add the ClockBuffer class for
backward compatibility with the MIPS32 bench. Have to review this
functionnality coming from the deprecated placeAndroute.py.
In st_instance.py, no longer creates the Plug ring of a Net.
In my opinion it just clutter the display until the P&R is called.
Can re-enable later as an option (in Unicorn).
* Change: In Unicorn, in cgt.py, more reliable way of loading then running
user supplied scripts. Borrowed from alliance-checker-toolkit doChip.py .
2015-08-16 16:29:28 -05:00
|
|
|
sort( _costs.begin(), _costs.end(), TrackCost::Compare(flags) );
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
size_t i=0;
|
|
|
|
for ( ; (i<_costs.size()) and _costs[i].isFree() ; i++ );
|
|
|
|
_event->setTracksFree ( i );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SegmentFsm::addAction ( TrackElement* segment
|
|
|
|
, unsigned int type
|
|
|
|
, DbU::Unit axisHint
|
|
|
|
, unsigned int toSegmentFsm )
|
|
|
|
{
|
|
|
|
if ( not segment->isFixed() ) {
|
|
|
|
_actions.push_back ( SegmentAction(segment,type,axisHint,toSegmentFsm) );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::addAction(): " << segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SegmentFsm::doActions ()
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::doActions() - " << _actions.size() << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
bool ripupOthersParallel = false;
|
|
|
|
bool ripedByLocal = getEvent()->getSegment()->isLocal();
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_actions.size() ; i++ ) {
|
|
|
|
if ( ripedByLocal ) _actions[i].setFlag ( SegmentAction::RipedByLocal );
|
|
|
|
if ( _actions[i].getType() & SegmentAction::OtherRipup ) {
|
|
|
|
ripupOthersParallel = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( size_t i=0 ; i<_actions.size() ; i++ ) {
|
|
|
|
if ( (_actions[i].getType() & SegmentAction::SelfInsert) and ripupOthersParallel )
|
|
|
|
_actions[i].setFlag ( SegmentAction::EventLevel3 );
|
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
DebugSession::open ( _actions[i].getSegment()->getNet(), 150, 160 );
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( not _actions[i].doAction(_queue) ) {
|
|
|
|
cinfo << "[INFO] Failed action on " << _actions[i].getSegment() << endl;
|
|
|
|
}
|
|
|
|
DebugSession::close ();
|
|
|
|
}
|
|
|
|
|
|
|
|
_actions.clear ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::insertInTrack ( size_t i )
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::insertInTrack() istate:" << _event->getInsertState()
|
2013-12-03 18:59:29 -06:00
|
|
|
<< " track:" << i << endl;
|
|
|
|
|
|
|
|
_event->incInsertState();
|
|
|
|
switch ( _event->getInsertState() ) {
|
|
|
|
case 1:
|
|
|
|
if ( Manipulator(_event->getSegment(),*this).insertInTrack(i) ) return true;
|
|
|
|
_event->incInsertState();
|
|
|
|
case 2:
|
|
|
|
if ( Manipulator(_event->getSegment(),*this).shrinkToTrack(i) ) return true;
|
|
|
|
_event->incInsertState();
|
|
|
|
case 3:
|
|
|
|
if ( Manipulator(_event->getSegment(),*this).forceToTrack(i) ) return true;
|
|
|
|
_event->incInsertState();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::conflictSolveByHistory ()
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
RipupHistory ripupHistory ( _event );
|
|
|
|
RoutingEvent* event;
|
|
|
|
TrackElement* segment = _event->getSegment();
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::conflictSolveByHistory()" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
size_t maxDepth = min( getHistory().size(), (size_t)300 );
|
|
|
|
size_t depth = 0;
|
|
|
|
while ( (ripupHistory.getDislodgersCount() < 3) and (depth < maxDepth) ) {
|
|
|
|
event = getHistory().getRNth(depth++);
|
|
|
|
if (not event) continue;
|
|
|
|
if ( (event->getSegment() != segment) and ripupHistory.isDislodger(event) )
|
|
|
|
ripupHistory.addDislodger( event );
|
|
|
|
}
|
|
|
|
|
|
|
|
//ripupHistory.print ( cout );
|
|
|
|
|
|
|
|
UnionIntervals* intervals = ripupHistory.getUnionIntervals( segment->getAxis() );
|
|
|
|
if (intervals and not intervals->empty()) {
|
|
|
|
|
|
|
|
DbU::Unit minConflict = intervals->getVMin();
|
|
|
|
DbU::Unit maxConflict = intervals->getVMax();
|
|
|
|
Interval canonical = segment->getCanonicalInterval();
|
|
|
|
bool sourceDogleg = canonical.contains(minConflict);
|
|
|
|
bool targetDogleg = canonical.contains(maxConflict);
|
|
|
|
Point breakPoint;
|
|
|
|
|
|
|
|
if (sourceDogleg) {
|
|
|
|
if (segment->isHorizontal()) {
|
|
|
|
breakPoint = Point( minConflict, segment->getAxis() );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << breakPoint << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
|
|
|
breakPoint = Point( segment->getAxis(), minConflict );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << breakPoint << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Katabatic::GCell* dogLegGCell = Session::getGCellUnder( breakPoint.getX(), breakPoint.getY() );
|
|
|
|
if (dogLegGCell) {
|
|
|
|
if (segment->canDogleg(dogLegGCell))
|
|
|
|
success = segment->makeDogleg(dogLegGCell);
|
|
|
|
} else {
|
|
|
|
cerr << Bug( "No GCell under source %s for:\n %s."
|
|
|
|
, getString(breakPoint).c_str(), getString(segment).c_str() ) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not success and targetDogleg) {
|
|
|
|
if (segment->isHorizontal()) {
|
|
|
|
breakPoint = Point( maxConflict, segment->getAxis() );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << breakPoint << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
|
|
|
breakPoint = Point( segment->getAxis(), maxConflict );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << breakPoint << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Katabatic::GCell* dogLegGCell = Session::getGCellUnder( breakPoint.getX(), breakPoint.getY() );
|
|
|
|
if (dogLegGCell) {
|
|
|
|
if (segment->canDogleg(dogLegGCell)) {
|
|
|
|
success = segment->makeDogleg(dogLegGCell);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
cerr << Bug( "No GCell under target %s for:\n %s."
|
|
|
|
, getString(breakPoint).c_str(), getString(segment).c_str() ) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "No disloggers found @" << DbU::getValueString(segment->getAxis()) << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
Interval freeSpan = Session::getKiteEngine()->
|
|
|
|
getTrackByPosition(segment->getLayer(),segment->getAxis())->
|
|
|
|
getFreeInterval(segment->getSourceU(),segment->getNet());
|
|
|
|
|
|
|
|
if (freeSpan.contains(segment->getCanonicalInterval())) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Disloggers vanished, Segment can be re-inserted." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::conflictSolveByPlaceds ()
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
Interval constraints;
|
|
|
|
vector<Cs1Candidate> candidates;
|
|
|
|
TrackElement* segment = _event->getSegment();
|
In Katabatic, the layer assignment move up part of Net trunks.
* In Katabatic, in AutoSegment::canMoveUp(), adds the ability to reject
the move up if the density of the depth we comes from is below 0.6
in all the GCells, activated with the KbChecklowDensity flag.
* In Katabatic, In LayerAssign, new method moveUpNetTrunk2() which,
unlike the previous one, move up only the part of the Net trunk
which is connex to the seed segment. Use the canMoveUp with
low density checking to avoid unbalancing higher metal layers.
* In Kite, in SegmentFsm, use the canMoveUp() with low density checking.
2016-03-15 12:06:43 -05:00
|
|
|
bool canMoveUp = (segment->isLocal()) ? segment->canPivotUp(0.5) : segment->canMoveUp(1.0,Katabatic::KbCheckLowDensity); // MARK 1
|
2013-12-03 18:59:29 -06:00
|
|
|
unsigned int relaxFlags = Manipulator::NoDoglegReuse
|
|
|
|
| ((_data and (_data->getStateCount() < 2)) ? Manipulator::AllowExpand
|
|
|
|
: Manipulator::NoExpand);
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::conflictSolveByPlaceds()" << endl;
|
|
|
|
cdebug_log(159,0) << "| Candidates Tracks: " << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
segment->base()->getConstraints( constraints );
|
|
|
|
Interval overlap = segment->getCanonicalInterval();
|
|
|
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segment->getLayer());
|
|
|
|
Track* track = plane->getTrackByPosition(constraints.getVMin(),Constant::Superior);
|
|
|
|
|
|
|
|
if (not track) {
|
|
|
|
cerr << Bug( "SegmentFsm::conflictSolveByPlaceds():\n"
|
|
|
|
" For: %s\n"
|
|
|
|
" In %s, no Track near %s"
|
|
|
|
, getString(segment).c_str()
|
|
|
|
, getString(plane).c_str()
|
|
|
|
, DbU::getValueString(constraints.getVMin()).c_str()
|
|
|
|
) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( ; track and track->getAxis() <= constraints.getVMax() ; track = track->getNextTrack() ) {
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
candidates.push_back( Cs1Candidate(track,segment->getPPitch()) );
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
size_t begin;
|
|
|
|
size_t end;
|
|
|
|
TrackElement* other;
|
|
|
|
Net* otherNet = NULL;
|
|
|
|
Interval otherOverlap;
|
|
|
|
bool otherIsGlobal = false;
|
|
|
|
|
|
|
|
track->getOverlapBounds( overlap, begin, end );
|
|
|
|
candidates.back().setBegin( begin );
|
|
|
|
candidates.back().setEnd ( end );
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "* " << track << " [" << begin << ":" << end << "]" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
for ( ; (begin < end) ; ++begin ) {
|
|
|
|
other = track->getSegment( begin );
|
|
|
|
|
|
|
|
if (other->getNet() == segment->getNet()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | " << begin << " Same net: " << " " << other << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (not other->getCanonicalInterval().intersect(overlap)) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | " << begin << " No Conflict: " << " " << other << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if (otherNet == NULL) candidates.back().setBegin( begin+1 );
|
|
|
|
continue;
|
|
|
|
}
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | " << begin << " Conflict: " << " " << other << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if (otherNet != other->getNet()) {
|
|
|
|
if (otherNet) {
|
|
|
|
if (otherIsGlobal) {
|
|
|
|
candidates.back().addConflict( otherOverlap );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | Other overlap G: " << otherOverlap << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | Other overlap L: " << otherOverlap << " ignored." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
otherNet = other->getNet();
|
|
|
|
otherOverlap = other->getCanonicalInterval();
|
2014-09-14 11:54:10 -05:00
|
|
|
otherIsGlobal = other->isGlobal() or other->isBlockage() or other->isFixed();
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
|
|
|
otherOverlap.merge(other->getCanonicalInterval());
|
2014-09-14 11:54:10 -05:00
|
|
|
otherIsGlobal = otherIsGlobal or other->isGlobal() or other->isBlockage() or other->isFixed();
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (not otherOverlap.isEmpty()) {
|
|
|
|
if (otherIsGlobal) {
|
|
|
|
candidates.back().addConflict( otherOverlap );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | Other overlap G: " << otherOverlap << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
} else {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << " | Other overlap L: " << otherOverlap << " ignored." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
candidates.back().consolidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
sort( candidates.begin(), candidates.end() );
|
|
|
|
|
|
|
|
for ( size_t icandidate=0 ; icandidate<candidates.size() ; ++icandidate ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Trying l:" << candidates[icandidate].getLength()
|
2013-12-03 18:59:29 -06:00
|
|
|
<< " " << candidates[icandidate].getTrack() << endl;
|
|
|
|
|
|
|
|
Interval overlap0 = candidates[icandidate].getLongestConflict();
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "overlap0: " << overlap0 << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if (overlap0.isEmpty()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "overlap0 is empty, no conflict, ignoring Track candidate." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Track* track = candidates[icandidate].getTrack();
|
|
|
|
TrackElement* other = track->getSegment( overlap.getCenter() );
|
|
|
|
if (not other) {
|
|
|
|
cbug << Error("conflictSolveByPlaceds(): No segment under overlap center.") << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (other->isGlobal()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "conflictSolveByPlaceds() - Conflict with global, other move up" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ((success = Manipulator(other,*this).moveUp())) break;
|
|
|
|
}
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "conflictSolveByPlaceds() - Relaxing self" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if (Manipulator(segment,*this).relax(overlap0,relaxFlags)) {
|
|
|
|
success = true;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if ( not canMoveUp
|
|
|
|
and (relaxFlags != Manipulator::NoExpand)
|
|
|
|
and Manipulator(segment,*this).relax(overlap0,Manipulator::NoExpand|Manipulator::NoDoglegReuse) ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Cannot move up but successful narrow breaking." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
success = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( not success and segment->isGlobal() and (_costs.size() <= 1) ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Overconstrained perpandiculars, rip them up. On track:" << endl;
|
|
|
|
cdebug_log(159,0) << " " << track << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
Manipulator(segment,*this).ripupPerpandiculars ();
|
|
|
|
success = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::solveTerminalVsGlobal ()
|
|
|
|
{
|
|
|
|
TrackElement* segment = getEvent()->getSegment();
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "SegmentFsm::solveTerminalVsGlobal: " << " " << segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if (not (segment->isTerminal() and segment->isLocal())) return false;
|
|
|
|
|
|
|
|
for ( size_t icost=0 ; icost<_costs.size() ; ++icost ) {
|
|
|
|
Interval overlap = segment->getCanonicalInterval();
|
|
|
|
size_t begin;
|
|
|
|
size_t end;
|
|
|
|
getCost(icost).getTrack()->getOverlapBounds( overlap, begin, end );
|
|
|
|
|
|
|
|
for ( ; begin<end ; ++begin ) {
|
|
|
|
TrackElement* other = getCost(icost).getTrack()->getSegment(begin);
|
|
|
|
Interval otherOverlap = other->getCanonicalInterval();
|
|
|
|
|
|
|
|
if (other->getNet() == segment->getNet()) continue;
|
|
|
|
if (not other->isGlobal()) continue;
|
|
|
|
if (not otherOverlap.contains(overlap)) continue;
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| Global candidate:" << other << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if (Manipulator(other,*this).moveUp(Manipulator::AllowTerminalMoveUp)) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| Global candidate selected." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::solveFullBlockages ()
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
TrackElement* segment = getEvent()->getSegment();
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,1) << "SegmentFsm::solveFullBlockages: " << " " << segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if ( segment->isLocal() ) {
|
|
|
|
success = Manipulator(segment,*this).pivotUp();
|
|
|
|
if ( not success ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Tightly constrained local segment overlapping a blockage, move up." << endl;
|
|
|
|
cdebug_log(159,0) << segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
success = Manipulator(segment,*this).moveUp
|
|
|
|
(Manipulator::AllowLocalMoveUp|Manipulator::AllowTerminalMoveUp);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Interval overlap = segment->getCanonicalInterval();
|
|
|
|
size_t begin;
|
|
|
|
size_t end;
|
|
|
|
|
|
|
|
getCost(0).getTrack()->getOverlapBounds ( overlap, begin, end );
|
|
|
|
for ( ; begin<end ; ++begin ) {
|
|
|
|
TrackElement* other = getCost(0).getTrack()->getSegment(begin);
|
|
|
|
Interval otherOverlap = other->getCanonicalInterval();
|
|
|
|
|
|
|
|
if ( other->getNet() == segment->getNet() ) continue;
|
|
|
|
if ( not otherOverlap.intersect(overlap) ) continue;
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| " << begin << " Blockage conflict: " << " " << other << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( (success = Manipulator(segment,*this).relax
|
|
|
|
(otherOverlap,Manipulator::NoDoglegReuse|Manipulator::NoExpand)) ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( not success ) {
|
|
|
|
cparanoid << Error( "Tighly constrained segment overlapping a blockage:\n %s"
|
|
|
|
, getString(segment).c_str() ) << endl;
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Segment is hard blocked, bypass to Unimplemented." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_tabw(159,-1);
|
2013-12-03 18:59:29 -06:00
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::desaturate ()
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,1) << "SegmentFsm::desaturate()" << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
size_t itrack = 0;
|
|
|
|
|
|
|
|
#if THIS_IS_DISABLED
|
|
|
|
TrackElement* segment = _event->getSegment();
|
|
|
|
for ( ; itrack<getCosts().size() ; ++itrack ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Trying track:" << itrack << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if ( getCost(itrack).isGlobalEnclosed() ) {
|
|
|
|
Track* track = getTrack(itrack);
|
|
|
|
size_t begin = getBegin(itrack);
|
|
|
|
size_t end = getEnd (itrack);
|
|
|
|
Net* ownerNet = segment->getNet();
|
|
|
|
Interval toFree (segment->getCanonicalInterval());
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
for ( size_t i = begin ; success and (i < end) ; i++ ) {
|
|
|
|
TrackElement* segment2 = track->getSegment(i);
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
if ( segment2->getNet() == ownerNet ) continue;
|
|
|
|
if ( not toFree.intersect(segment2->getCanonicalInterval()) ) continue;
|
|
|
|
if ( segment2->isFixed() or not segment2->isBipoint() ) {
|
|
|
|
success = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataNegociate* data2 = segment2->getDataNegociate();
|
|
|
|
if ( not data2 ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "No DataNegociate, ignoring." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
success = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "- Forced moveUp " << segment2 << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ( not (success=Manipulator(segment2,*this).moveUp(Manipulator::AllowTerminalMoveUp)) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( success ) {
|
|
|
|
setState ( SegmentFsm::OtherRipup );
|
|
|
|
addAction( segment
|
|
|
|
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis
|
|
|
|
, getCost(itrack).getTrack()->getAxis()
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_tabw(159,-1);
|
2013-12-03 18:59:29 -06:00
|
|
|
return (itrack < _costs.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::_slackenStrap ( TrackElement*& segment, DataNegociate*& data, unsigned int flags )
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Strap segment Fsm." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
unsigned int nextState = data->getState();
|
|
|
|
|
|
|
|
switch ( data->getState() ) {
|
|
|
|
case DataNegociate::RipupPerpandiculars:
|
|
|
|
nextState = DataNegociate::Minimize;
|
|
|
|
success = Manipulator(segment,*this).ripupPerpandiculars();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::Minimize:
|
|
|
|
if (data->getStateCount() >= 2) {
|
|
|
|
nextState = DataNegociate::MaximumSlack;
|
|
|
|
}
|
|
|
|
success = Manipulator(segment,*this).minimize();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::Dogleg:
|
|
|
|
case DataNegociate::Slacken:
|
|
|
|
case DataNegociate::ConflictSolveByHistory:
|
|
|
|
case DataNegociate::ConflictSolveByPlaceds:
|
|
|
|
case DataNegociate::MoveUp:
|
|
|
|
case DataNegociate::MaximumSlack:
|
|
|
|
case DataNegociate::Unimplemented:
|
|
|
|
nextState = DataNegociate::Unimplemented;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not success and (nextState != DataNegociate::Unimplemented))
|
|
|
|
success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit);
|
|
|
|
|
|
|
|
if (not (flags&NoTransition)) {
|
|
|
|
data->setState( nextState );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Incrementing state (after): " << nextState << " count:" << data->getStateCount() << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::_slackenLocal ( TrackElement*& segment, DataNegociate*& data, unsigned int flags )
|
|
|
|
{
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Local segment Fsm." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
bool success = false;
|
|
|
|
unsigned int nextState = data->getState();
|
|
|
|
|
|
|
|
switch (data->getState()) {
|
|
|
|
case DataNegociate::RipupPerpandiculars:
|
|
|
|
nextState = DataNegociate::Minimize;
|
|
|
|
success = Manipulator(segment,*this).ripupPerpandiculars();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::Minimize:
|
|
|
|
if (isFullBlocked() and not segment->isTerminal()) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Is Fully blocked." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
nextState = DataNegociate::Unimplemented;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nextState = DataNegociate::Dogleg;
|
|
|
|
success = Manipulator(segment,*this).minimize();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::Dogleg:
|
|
|
|
nextState = DataNegociate::Slacken;
|
|
|
|
success = Manipulator(segment,*this).makeDogleg();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::Slacken:
|
|
|
|
nextState = DataNegociate::ConflictSolveByPlaceds;
|
|
|
|
success = Manipulator(segment,*this).slacken();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::ConflictSolveByHistory:
|
|
|
|
case DataNegociate::ConflictSolveByPlaceds:
|
|
|
|
nextState = DataNegociate::LocalVsGlobal;
|
|
|
|
success = conflictSolveByHistory();
|
|
|
|
break;
|
|
|
|
case DataNegociate::LocalVsGlobal:
|
|
|
|
nextState = DataNegociate::MoveUp;
|
|
|
|
success = solveTerminalVsGlobal();
|
|
|
|
if (success) break;
|
|
|
|
break;
|
|
|
|
case DataNegociate::MoveUp:
|
|
|
|
nextState = DataNegociate::MaximumSlack;
|
|
|
|
success = Manipulator(segment,*this).moveUp();
|
|
|
|
if (success) break;
|
|
|
|
case DataNegociate::MaximumSlack:
|
|
|
|
if (segment->isStrap()) {
|
|
|
|
if ( (nextState < DataNegociate::MaximumSlack) or (data->getStateCount() < 2) ) {
|
|
|
|
nextState = DataNegociate::MaximumSlack;
|
|
|
|
success = conflictSolveByPlaceds();
|
|
|
|
if (success) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case DataNegociate::Unimplemented:
|
|
|
|
nextState = DataNegociate::Unimplemented;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not success and (nextState != DataNegociate::Unimplemented)) {
|
|
|
|
if (data->getStateCount() < 6)
|
|
|
|
success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not success
|
|
|
|
and (nextState == DataNegociate::Unimplemented)
|
|
|
|
and segment->isSlackened()
|
|
|
|
and isFullBlocked()) {
|
|
|
|
if (solveFullBlockages()) nextState = DataNegociate::MoveUp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not (flags&NoTransition)) {
|
|
|
|
data->setState( nextState );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Incrementing state (after): " << nextState << " count:" << data->getStateCount() << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::_slackenGlobal ( TrackElement*& segment, DataNegociate*& data, unsigned int flags )
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
unsigned int nextState = data->getState();
|
|
|
|
|
|
|
|
switch ( data->getState() ) {
|
|
|
|
case DataNegociate::RipupPerpandiculars:
|
|
|
|
case DataNegociate::Minimize:
|
|
|
|
case DataNegociate::Dogleg:
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Global, SegmentFsm: RipupPerpandiculars." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
nextState = DataNegociate::Slacken;
|
|
|
|
break;
|
|
|
|
case DataNegociate::Slacken:
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Global, SegmentFsm: Slacken." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ((success = Manipulator(segment,*this).slacken(KbHalfSlacken))) {
|
|
|
|
nextState = DataNegociate::RipupPerpandiculars;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DataNegociate::MoveUp:
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Global, SegmentFsm: MoveUp." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ((success = Manipulator(segment,*this).moveUp(Manipulator::AllowShortPivotUp))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nextState = DataNegociate::ConflictSolveByHistory;
|
|
|
|
break;
|
|
|
|
case DataNegociate::ConflictSolveByHistory:
|
|
|
|
case DataNegociate::ConflictSolveByPlaceds:
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Global, SegmentFsm: ConflictSolveByHistory or ConflictSolveByPlaceds." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if ((success = conflictSolveByPlaceds())) {
|
In Katabatic, the layer assignment move up part of Net trunks.
* In Katabatic, in AutoSegment::canMoveUp(), adds the ability to reject
the move up if the density of the depth we comes from is below 0.6
in all the GCells, activated with the KbChecklowDensity flag.
* In Katabatic, In LayerAssign, new method moveUpNetTrunk2() which,
unlike the previous one, move up only the part of the Net trunk
which is connex to the seed segment. Use the canMoveUp with
low density checking to avoid unbalancing higher metal layers.
* In Kite, in SegmentFsm, use the canMoveUp() with low density checking.
2016-03-15 12:06:43 -05:00
|
|
|
if (segment->canMoveUp(1.0,Katabatic::KbCheckLowDensity))
|
2013-12-03 18:59:29 -06:00
|
|
|
nextState = DataNegociate::MoveUp;
|
|
|
|
else {
|
|
|
|
if (data->getStateCount() > 3)
|
|
|
|
nextState = DataNegociate::MaximumSlack;
|
|
|
|
}
|
|
|
|
if (segment->getDataNegociate()->getState() < DataNegociate::ConflictSolveByHistory)
|
|
|
|
nextState = segment->getDataNegociate()->getState();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DataNegociate::MaximumSlack:
|
|
|
|
if ((success=Manipulator(segment,*this).forceOverLocals())) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DataNegociate::Unimplemented:
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Global, SegmentFsm: MaximumSlack or Unimplemented." << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
nextState = DataNegociate::Unimplemented;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not success and (nextState != DataNegociate::Unimplemented)) {
|
|
|
|
if (data->getStateCount() < 6)
|
|
|
|
success = Manipulator(segment,*this).ripupPerpandiculars(Manipulator::ToRipupLimit);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case: all tracks are overlaping a blockage.
|
|
|
|
if (not success
|
|
|
|
and (nextState == DataNegociate::Unimplemented)
|
|
|
|
and segment->isSlackened() ) {
|
|
|
|
if (solveFullBlockages()) nextState = DataNegociate::MoveUp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not (flags&NoTransition)) {
|
|
|
|
if (data->getChildSegment()) {
|
|
|
|
TrackElement* child = segment;
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Incrementing state of childs (after): " << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
while ( child ) {
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| " << child << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
if (child->base()->isGlobal()) {
|
|
|
|
child->getDataNegociate()->setState( nextState );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "| Update:" << nextState << " count:" << child->getDataNegociate()->getStateCount() << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
TrackElement* parent = child;
|
|
|
|
child = parent->getDataNegociate()->getChildSegment();
|
|
|
|
parent->getDataNegociate()->setChildSegment( NULL );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
data->setState( nextState );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,0) << "Incrementing state (after): " << segment << endl;
|
|
|
|
cdebug_log(159,0) << "| " << nextState << " count:" << data->getStateCount() << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SegmentFsm::slackenTopology ( unsigned int flags )
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
TrackElement* segment = getEvent()->getSegment();
|
|
|
|
DataNegociate* data = segment->getDataNegociate ();
|
|
|
|
unsigned int actionFlags = SegmentAction::SelfInsert|SegmentAction::EventLevel5;
|
|
|
|
|
2016-05-17 16:00:06 -05:00
|
|
|
DebugSession::open( segment->getNet(), 150, 160 );
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_log(159,1) << "Slacken Topology for " << segment->getNet()
|
2016-05-17 16:00:06 -05:00
|
|
|
<< " " << segment << endl;
|
2013-12-03 18:59:29 -06:00
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
if (not segment or not data) { cdebug_tabw(159,-1); DebugSession::close(); return false; }
|
2013-12-03 18:59:29 -06:00
|
|
|
|
|
|
|
_event->resetInsertState();
|
|
|
|
data->resetRipupCount();
|
|
|
|
|
|
|
|
if (segment->isStrap()) { success = _slackenStrap ( segment, data, flags ); }
|
|
|
|
else if (segment->isLocal()) { success = _slackenLocal ( segment, data, flags ); }
|
|
|
|
else { success = _slackenGlobal( segment, data, flags ); }
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
actionFlags |= SegmentAction::ResetRipup;
|
|
|
|
addAction( segment, actionFlags );
|
|
|
|
} else {
|
|
|
|
clearActions();
|
|
|
|
if (data->getState() == DataNegociate::Unimplemented) {
|
|
|
|
cinfo << "[UNSOLVED] " << segment << " unable to slacken topology." << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-11 14:56:12 -05:00
|
|
|
cdebug_tabw(159,-1);
|
2013-12-03 18:59:29 -06:00
|
|
|
DebugSession::close();
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // Kite namespace.
|