coriolis/katana/src/Manipulator.cpp

1420 lines
52 KiB
C++
Raw Normal View History

Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2016, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | K i t e - D e t a i l e d R o u t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | =============================================================== |
// | C++ Module : "./Manipulator.cpp" |
// +-----------------------------------------------------------------+
#include "hurricane/DebugSession.h"
#include "hurricane/Bug.h"
#include "katana/TrackSegment.h"
#include "katana/Track.h"
#include "katana/Tracks.h"
#include "katana/DataNegociate.h"
#include "katana/RoutingPlane.h"
#include "katana/RoutingEvent.h"
#include "katana/SegmentFsm.h"
#include "katana/Manipulator.h"
#include "katana/KatanaEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace Katana;
using Anabatic::GCell;
// -------------------------------------------------------------------
// Class : "LvGCandidate".
class LvGCandidate {
public:
struct Compare : public binary_function<LvGCandidate&,LvGCandidate&,bool> {
inline bool operator() ( const LvGCandidate& lhs, const LvGCandidate& rhs ) const;
};
public:
inline LvGCandidate ( TrackElement* segment=NULL, Interval overlap=Interval(), size_t terminals=0 );
inline TrackElement* getSegment () const;
inline const Interval& getOverlap () const;
inline size_t getTerminals () const;
private:
TrackElement* _segment;
Interval _overlap;
size_t _terminals;
};
inline LvGCandidate::LvGCandidate ( TrackElement* segment, Interval overlap, size_t terminals )
: _segment (segment)
, _overlap (overlap)
, _terminals(terminals)
{ }
inline TrackElement* LvGCandidate::getSegment () const { return _segment; }
inline const Interval& LvGCandidate::getOverlap () const { return _overlap; }
inline size_t LvGCandidate::getTerminals () const { return _terminals; }
inline bool LvGCandidate::Compare::operator() ( const LvGCandidate& lhs, const LvGCandidate& rhs ) const
{
if ( lhs.getTerminals() != rhs.getTerminals() )
return lhs.getTerminals() < rhs.getTerminals();
if ( lhs.getOverlap() != rhs.getOverlap() )
return lhs.getOverlap().getSize() > rhs.getOverlap().getSize();
return lhs.getSegment()->getAxis() < rhs.getSegment()->getAxis();
}
} // Anonymous namespace.
namespace Katana {
using Hurricane::Bug;
// -------------------------------------------------------------------
// Class : "Manipulator".
Manipulator::Manipulator ( TrackElement* segment, SegmentFsm& S )
: _segment(segment)
, _data (NULL)
, _event (NULL)
, _fsm (S)
{
if (not _segment)
throw Error( "Manipulator::Manipulator(): cannot build upon a NULL TrackElement." );
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
DebugSession::open( _segment->getNet(), 156, 160 );
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
_data = _segment->getDataNegociate();
if (_data) _event = _data->getRoutingEvent();
}
Manipulator::~Manipulator ()
{ DebugSession::close(); }
bool Manipulator::canRipup ( unsigned int flags ) const
{
if (_data) {
if (not _event or _event->isUnimplemented()) return false;
unsigned int limit = Session::getKatanaEngine()->getRipupLimit(_segment);
unsigned int count = _data->getRipupCount() + ((flags & NotOnLastRipup) ? 1 : 0);
return (count < limit);
}
return false;
}
bool Manipulator::isCaged ( DbU::Unit axis ) const
{
Track* track = _segment->getTrack();
if ( not track ) return false;
TrackElement* neighbor = _segment->getPrevious();
if (neighbor and (neighbor->isFixed() or neighbor->isBlockage())) {
if (abs(axis - neighbor->getTargetU()) < getPPitch()*2)
return true;
}
neighbor = _segment->getNext();
if (neighbor and (neighbor->isFixed() or neighbor->isBlockage())) {
if (abs(axis - neighbor->getSourceU()) < getPPitch()*2)
return true;
}
return false;
}
bool Manipulator::ripup ( unsigned int type, DbU::Unit axisHint )
{
cdebug_log(159,0) << "Manipulator::ripup() " << endl;
if (not canRipup()) return false;
if (_segment->isFixed()) return false;
if (_data == NULL) return true;
_fsm.addAction( _segment, type, axisHint );
return true;
}
bool Manipulator::ripupPerpandiculars ( unsigned int flags )
{
cdebug_log(159,0) << "Manipulator::ripupPerpandiculars() - " << flags << endl;
bool success = true;
bool cagedPerpandiculars = false;
Interval constraints ( _event->getConstraints() );
Interval perpandicularConstraints ( constraints );
size_t placedPerpandiculars = 0;
unsigned int parallelActionFlags = SegmentAction::SelfRipup|SegmentAction::EventLevel4;
unsigned int perpandicularActionFlags = SegmentAction::SelfRipupPerpand;
if (flags & Manipulator::PerpandicularsFirst) {
parallelActionFlags &= ~SegmentAction::EventLevel4;
perpandicularActionFlags |= SegmentAction::EventLevel4;
if (flags & Manipulator::ToRipupLimit)
perpandicularActionFlags |= SegmentAction::ToRipupLimit;
} else {
if (flags & Manipulator::ToRipupLimit)
parallelActionFlags |= SegmentAction::ToRipupLimit;
}
cdebug_log(159,0) << "Pure constraints: " << constraints << endl;
Track* track = NULL;
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) {
track = perpandiculars[i]->getTrack();
if (not track) {
// The perpandicular is not placed yet.
if (flags & Manipulator::PerpandicularsFirst) {
_fsm.addAction( perpandiculars[i], perpandicularActionFlags );
}
continue;
}
bool dislodgeCaged = false;
if (Manipulator(perpandiculars[i],_fsm).isCaged(_event->getSegment()->getAxis())) {
cagedPerpandiculars = true;
dislodgeCaged = true;
}
placedPerpandiculars++;
// Try to ripup the perpandicular.
DataNegociate* data2 = perpandiculars[i]->getDataNegociate();
cdebug_log(159,0) << "| " << perpandiculars[i] << endl;
if ( (flags & Manipulator::ToMoveUp) and (data2->getState() < DataNegociate::MoveUp) )
data2->setState( DataNegociate::MoveUp );
if (Manipulator(perpandiculars[i],_fsm).ripup(perpandicularActionFlags)) {
if (dislodgeCaged) {
_event->setAxisHint( _event->getSegment()->getAxis() + _event->getSegment()->getPitch() );
}
continue;
}
// Cannot ripup the perpandicular, try to ripup it's neigbors.
size_t begin;
size_t end;
track->getOverlapBounds( constraints, begin, end );
for ( ; (begin < end) ; begin++ ) {
TrackElement* other = track->getSegment(begin);
if (other->getNet() == _event->getSegment()->getNet()) continue;
Interval otherCanonical ( other->getCanonicalInterval() );
if (not otherCanonical.intersect(constraints)) continue;
// Try to ripup conflicting neighbor.
if (Manipulator(other,_fsm).canRipup()) {
cdebug_log(159,0) << " | Ripup: " << begin << " " << other << endl;
_fsm.addAction( other, SegmentAction::OtherRipup );
} else {
cdebug_log(159,0) << "Aborted ripup of perpandiculars, fixed or blocked." << endl;
return false;
}
}
}
if (cagedPerpandiculars and not placedPerpandiculars) {
cdebug_log(159,0) << "Aborted ripup of perpandiculars, constraints are due to fixed/blockage." << endl;
_fsm.addAction( _segment, SegmentAction::SelfRipup );
return true;
}
if (_segment->isLocal() and not placedPerpandiculars) {
cdebug_log(159,0) << "No placed perpandiculars, tight native constraints, place perpandiculars FIRST." << endl;
for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) {
_fsm.addAction( perpandiculars[i], perpandicularActionFlags|SegmentAction::EventLevel4 );
}
_fsm.addAction( _segment, parallelActionFlags );
return true;
}
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_segment->getLayer());
size_t tracksNb = 0;
track = plane->getTrackByPosition(constraints.getVMin());
if (track and (track->getAxis() < constraints.getVMin())) track = track->getNextTrack();
for ( ; track && (track->getAxis() <= constraints.getVMax())
; track = track->getNextTrack(), tracksNb++ );
if (_segment->isLocal() and (tracksNb < 2)) success = ripple();
_fsm.addAction( _segment, parallelActionFlags );
return success;
}
bool Manipulator::relax ( Interval interval, unsigned int flags )
{
interval.inflate( - Session::getExtensionCap(getLayer()) );
cdebug_log(159,0) << "Manipulator::relax() of: " << _segment << " " << interval << endl;
if (_segment->isFixed()) return false;
if (not interval.intersect(_segment->getCanonicalInterval())) return false;
if (not _data) return false;
if ( _segment->isTerminal()
and (_segment->getLayer() == Session::getRoutingGauge()->getRoutingLayer(1)) ) {
if (interval.contains(_segment->base()->getAutoSource()->getX())) return false;
if (interval.contains(_segment->base()->getAutoTarget()->getX())) return false;
}
cdebug_tabw(159,1);
bool success = true;
bool expand = _segment->isGlobal() and (flags&AllowExpand);
cdebug_log(159,0) << "Expand:" << expand << endl;
vector<GCell*> gcells;
_segment->getGCells( gcells );
if (gcells.size() < 2) {
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
cerr << Bug( "relax() Cannot break %s,\n only in %s."
, getString(_segment).c_str()
, getString(gcells[0]).c_str()
) << endl;
cdebug_tabw(159,-1);
return false;
}
unsigned int depth = Session::getRoutingGauge()->getLayerDepth(_segment->getLayer());
Interval uside;
size_t dogLegCount = 0;
size_t iminconflict = gcells.size();
size_t imaxconflict = gcells.size();
size_t igcell;
// Look for closest enclosing min & max GCells indexes.
for ( igcell=0 ; igcell<gcells.size() ; igcell++ ) {
uside = gcells[igcell]->getSide(_segment->getDirection());
cdebug_log(159,0) << "| " << setw(3) << igcell << " " << gcells[igcell] << " uside: " << uside << endl;
if (uside.contains(interval.getVMin())) {
iminconflict = igcell;
cdebug_log(159,0) << "> Min conflict: " << iminconflict << endl;
}
if (uside.contains(interval.getVMax())) {
imaxconflict = igcell;
cdebug_log(159,0) << "> Max conflict: " << imaxconflict << endl;
}
}
// Expand min & max to enclose GCells of greatest or equal order
// (i.e. less saturateds)
bool minExpanded = false;
bool maxExpanded = false;
if (expand) {
if (iminconflict < gcells.size()) {
//cdebug_log(159,0) << "Expand min" << endl;
size_t imindensity = 0;
for ( size_t iexpand=1 ; iexpand<iminconflict ; ++iexpand ) {
if (not _segment->canDogleg(gcells[iexpand],Flags::AllowDoglegReuse)) continue;
// cdebug_log(159,0) << "<GCell [" << iexpand << "]> Density "
// << "Density " << Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
// << " min. dens.:" << gcells[imindensity]->getDensity(depth)
// << " exp. dens.:" << gcells[iexpand ]->getDensity(depth)
// << endl;
if (gcells[imindensity]->getDensity(depth) - gcells[iexpand]->getDensity(depth) > 1e-3) {
imindensity = iexpand;
//cdebug_log(159,0) << "Accepted expand " << imindensity << endl;
}
}
if (iminconflict != imindensity) minExpanded = true;
iminconflict = (imindensity>0) ? imindensity : gcells.size();
}
if (imaxconflict < gcells.size()) {
//cdebug_log(159,0) << "Expand max" << endl;
size_t imindensity = imaxconflict;
for ( size_t iexpand=imaxconflict+1 ; iexpand<gcells.size() ; ++iexpand ) {
if (not _segment->canDogleg(gcells[iexpand],Flags::AllowDoglegReuse)) continue;
// cdebug_log(159,0) << "<GCell [" << iexpand << "]> Density "
// << Session::getRoutingGauge()->getRoutingLayer(depth)->getName()
// << " min. dens.:" << gcells[imindensity]->getDensity(depth)
// << " exp. dens.:" << gcells[iexpand ]->getDensity(depth)
// << endl;
if (gcells[imindensity]->getDensity(depth) - gcells[iexpand]->getDensity(depth) > 1e-3) {
imindensity = iexpand;
//cdebug_log(159,0) << "Accepted expand " << imindensity << endl;
}
}
if (imindensity != imaxconflict) maxExpanded = true;
imaxconflict = (imindensity < gcells.size()) ? imindensity : gcells.size();
}
}
cdebug_log(159,0) << "minExpanded:" << minExpanded << " (" << iminconflict
<< ") maxExpanded:" << maxExpanded << " (" << imaxconflict << ")" << endl;
// Check for full enclosure.
if ( ( (iminconflict == gcells.size()) and (imaxconflict == gcells.size() ) )
or ( (iminconflict == 0) and (imaxconflict == gcells.size()-1) )) {
cinfo << "[INFO] Manipulator::relax(): Segment fully enclosed in interval." << endl;
cdebug_tabw(159,-1);
return false;
}
// Suppress min/max if it's the first/last.
if ((iminconflict < gcells.size()) and (imaxconflict == gcells.size()-1)) imaxconflict = gcells.size();
if ((imaxconflict < gcells.size()) and (iminconflict == 0)) iminconflict = gcells.size();
// Compute number of doglegs and nature of the *first* dogleg.
// (first can be min or max, second can only be max)
bool firstDoglegIsMin = false;
if (iminconflict < gcells.size()) { dogLegCount++; firstDoglegIsMin = true; }
if (imaxconflict < gcells.size()) dogLegCount++;
switch ( dogLegCount ) {
case 2:
// Compact only if the double dogleg is at beginning or end.
if (iminconflict == imaxconflict) {
if (iminconflict == 0) {
// First dogleg is max.
dogLegCount--;
} else if (iminconflict == gcells.size()-1) {
dogLegCount--;
firstDoglegIsMin = true;
}
}
break;
case 1: break;
case 0:
cerr << Bug( "Manipulator::relax() Can't find a GCell suitable for making dogleg."
, getString(interval).c_str() ) << endl;
cdebug_tabw(159,-1);
return false;
}
cdebug_log(159,0) << "| Has to do " << dogLegCount << " doglegs." << endl;
// Check of "min is less than one track close the edge" (while not expanded).
// AND we are on the first GCell AND there's one dogleg only.
if (not minExpanded and (iminconflict == 0) and (imaxconflict == gcells.size())) {
cdebug_log(159,0) << "Cannot break in first GCell only." << endl;
cdebug_tabw(159,-1);
return false;
}
// Check of "min is less than one track close the edge" (while not expanded).
if ( /*not minExpanded and*/ (iminconflict > 0) and (iminconflict < gcells.size()) ) {
uside = gcells[iminconflict-1]->getSide(_segment->getDirection());
cdebug_log(159,0) << "GCell Edge Comparison (min): " << uside
<< " vs. " << DbU::getValueString(interval.getVMin()) << endl;
// Ugly: One lambda shrink.
if (interval.getVMin()-DbU::lambda(1.0) <= uside.getVMax()) {
cdebug_log(159,0) << "Using previous GCell." << endl;
iminconflict--;
}
}
// Check if there is only one dogleg AND it's the last one.
if (not maxExpanded and (iminconflict == gcells.size()) and (imaxconflict == gcells.size()-1)) {
cdebug_log(159,0) << "Cannot break in last GCell only." << endl;
cdebug_tabw(159,-1);
return false;
}
// Check of "max is less than one track close the edge" (while not expanded).
if ((imaxconflict < gcells.size()-1)) {
uside = gcells[imaxconflict+1]->getSide( _segment->getDirection() );
cdebug_log(159,0) << "GCell Edge Comparison (max): " << uside
<< " vs. " << DbU::getValueString(interval.getVMax()) << endl;
if (interval.getVMax()+getPPitch() >= uside.getVMin()) {
interval.inflate( 0, getPPitch() );
cdebug_log(159,0) << "Using next GCell " << interval << endl;
imaxconflict++;
}
}
size_t ifirstDogleg = gcells.size();
size_t isecondDogleg = gcells.size();
if (not firstDoglegIsMin) {
ifirstDogleg = imaxconflict;
} else {
ifirstDogleg = iminconflict;
isecondDogleg = imaxconflict;
}
// Making first dogleg.
cdebug_log(159,0) << "Making FIRST dogleg at " << ifirstDogleg << endl;
TrackElement* segment1 = NULL;
TrackElement* segment2 = NULL;
Track* track = _segment->getTrack();
Anabatic::GCell* dogLegGCell = gcells[ifirstDogleg];
TrackElement* dogleg = NULL;
DbU::Unit doglegAxis;
bool doglegReuse1 = false;
bool doglegReuse2 = false;
// Try to reuse existing dogleg if broken at either end.
if (ifirstDogleg == 0) dogleg = _segment->getSourceDogleg();
if (ifirstDogleg == gcells.size()-1) dogleg = _segment->getTargetDogleg();
if (dogleg) {
cdebug_log(159,0) << "Reusing dogleg." << endl;
doglegReuse1 = true;
segment1 = _segment;
} else {
// Try to create a new dogleg.
if (not _segment->canDogleg(dogLegGCell)) {
cdebug_log(159,0) << "Cannot create FIRST dogleg." << endl;
cdebug_tabw(159,-1);
return false;
}
_segment->makeDogleg( dogLegGCell, dogleg, segment1 );
}
if (firstDoglegIsMin) {
if (minExpanded) {
doglegAxis = dogLegGCell->getSide( _segment->getDirection() ).getCenter();
//cdebug_log(159,0) << "MARK 1 doglegAxis: " << DbU::getValueString(doglegAxis) << endl;
} else {
doglegAxis = interval.getVMin() - getPPitch();
//cdebug_log(159,0) << "MARK 2 doglegAxis: " << DbU::getValueString(doglegAxis) << endl;
}
} else {
if (maxExpanded) {
doglegAxis = dogLegGCell->getSide( _segment->getDirection() ).getVMin();
//cdebug_log(159,0) << "MARK 3 doglegAxis: " << DbU::getValueString(doglegAxis) << endl;
} else {
doglegAxis = interval.getVMax() + getPPitch() - DbU::fromLambda(1.0);
//cdebug_log(159,0) << "MARK 4 doglegAxis: " << DbU::getValueString(doglegAxis) << endl;
}
}
if (doglegReuse1) _fsm.addAction( dogleg, SegmentAction::OtherRipup );
else dogleg->setAxis( doglegAxis );
// If event is present, the dogleg is in the current RoutingSet.
RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent();
if (event) {
cdebug_log(159,0) << "Set Axis Hint: @" << DbU::getValueString(doglegAxis) << " " << dogleg << endl;
event->setAxisHint( doglegAxis );
} else {
cdebug_log(159,0) << "Dogleg has no RoutingEvent yet." << endl;
}
// Making second dogleg.
if (dogLegCount > 1) {
cdebug_log(159,0) << "Making SECOND dogleg at " << isecondDogleg
<< " on " << segment1 << endl;
dogleg = NULL;
dogLegGCell = gcells[isecondDogleg];
if (ifirstDogleg == isecondDogleg) {
cdebug_log(159,0) << "Double break in same GCell." << endl;
segment1->setFlags( TElemSourceDogleg );
}
if (isecondDogleg == gcells.size()-1) dogleg = segment1->getTargetDogleg();
if (dogleg) {
cdebug_log(159,0) << "Reusing dogleg." << endl;
doglegReuse2 = true;
segment2 = segment1;
} else {
// Try to create a new dogleg.
if (not segment1->canDogleg(dogLegGCell)) {
cdebug_log(159,0) << "Cannot create SECOND dogleg." << endl;
cdebug_tabw(159,-1);
return false;
}
segment1->makeDogleg( dogLegGCell, dogleg, segment2 );
}
if (maxExpanded) {
doglegAxis = dogLegGCell->getSide(segment1->getDirection()/*,false*/).getCenter();
} else {
doglegAxis = interval.getVMax() + getPPitch();
}
if (doglegReuse2) _fsm.addAction( dogleg, SegmentAction::OtherRipup );
else dogleg->setAxis( doglegAxis );
// If event is present, the dogleg is in the current RoutingSet.
RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent();
if (event) {
cdebug_log(159,0) << "Set Axis Hint: @" << DbU::getValueString(doglegAxis) << " " << dogleg << endl;
event->setAxisHint( doglegAxis );
} else {
cdebug_log(159,0) << "Dogleg has no RoutingEvent yet." << endl;
}
// This cases seems never to occurs.
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
for ( size_t i=0 ; i<doglegs.size() ; i++ ) {
TrackElement* segment = Session::lookup(doglegs[i]);
if (not segment->getTrack() and track) {
cdebug_log(159,0) << "Direct Track insert of: " << segment << endl;
Session::addInsertEvent( segment, track );
}
}
}
switch ( dogLegCount ) {
case 1:
if (not doglegReuse1) {
if (firstDoglegIsMin)
_segment->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
else
segment1->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
}
if ((flags & NoDoglegReuse) and (doglegReuse1 or doglegReuse2 ))
success = false;
break;
case 2:
if (not doglegReuse1)
_segment->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
if ( not doglegReuse2 )
segment2->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
break;
}
if (_segment->isLocal()) {
cdebug_log(159,0) << "Reset state of: " << _segment << endl;
_segment->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
} else {
cdebug_log(159,0) << "No state reset: " << _segment << endl;
}
if ((not doglegReuse1) and segment1 and segment1->isLocal()) {
cdebug_log(159,0) << "Reset state of: " << segment1 << endl;
segment1->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
}
if ((not doglegReuse2) and segment2 and segment2->isLocal()) {
cdebug_log(159,0) << "Reset state of: " << segment2 << endl;
segment2->getDataNegociate()->setState( DataNegociate::RipupPerpandiculars, true );
}
cdebug_tabw(159,-1);
return success;
}
bool Manipulator::insertInTrack ( size_t itrack )
{
Track* track = _fsm.getTrack(itrack);
size_t begin = _fsm.getBegin(itrack);
size_t end = _fsm.getEnd (itrack);
Net* ownerNet = _segment->getNet();
Interval toFree (_segment->getCanonicalInterval());
//Net* ripupNet = NULL;
set<TrackElement*> canonicals;
DbU::Unit rightAxisHint = 0;
DbU::Unit leftAxisHint = 0;
bool leftIntrication = false;
bool rightIntrication = false;
bool success = true;
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
cdebug_log(159,1) << "Manipulator::insertInTrack(size_t) - " << toFree << endl;
cdebug_log(159,0) << _segment << endl;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
for ( size_t i = begin ; success && (i < end) ; i++ ) {
TrackElement* segment2 = track->getSegment(i);
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if ( segment2->getNet() == ownerNet ) continue;
if ( not toFree.intersect(segment2->getCanonicalInterval()) ) {
cdebug_log(159,0) << "No intersection with: " << segment2->getCanonicalInterval() << endl;
continue;
}
if ( segment2->isBlockage() or segment2->isFixed() ) {
cdebug_log(159,0) << "Ovelap is blockage or fixed." << endl;
success = false;
continue;
}
// if ( segment2->getId() >= maxId ) {
// cdebug_log(159,0) << "Ovelap has an Id superior to AutoSegment::maxId:" << maxId << "." << endl;
// continue;
// }
// ripupNet = segment2->getNet();
DataNegociate* data2 = segment2->getDataNegociate();
if ( !data2 ) {
cdebug_log(159,0) << "No DataNegociate, ignoring." << endl;
continue;
}
if ( data2->getState() == DataNegociate::MaximumSlack ) {
cdebug_log(159,0) << "At " << DataNegociate::getStateString(data2)
<< " for " << segment2 << endl;
success = false;
continue;
}
bool shrinkLeft = false;
bool shrinkRight = false;
if ( data2->getRightMinExtend() < toFree.getVMin() ) {
cdebug_log(159,0) << "- Shrink right edge (push left) " << segment2 << endl;
shrinkRight = true;
TrackElement* rightNeighbor2 = track->getSegment(i+1);
if ( rightNeighbor2 && (rightNeighbor2->getNet() == segment2->getNet()) ) {
Interval interval1 = segment2->getCanonicalInterval();
Interval interval2 = rightNeighbor2->getCanonicalInterval();
if ( interval1.intersect(interval2) && (interval2.getVMax() > interval1.getVMax()) )
shrinkLeft = true;
}
}
if ( data2->getLeftMinExtend() > toFree.getVMax() ) {
cdebug_log(159,0) << "- Shrink left edge (push right) " << segment2 << endl;
shrinkLeft = true;
if ( i > 0 ) {
TrackElement* leftNeighbor2 = track->getSegment(i-1);
if ( leftNeighbor2 && (leftNeighbor2->getNet() == segment2->getNet()) ) {
Interval interval1 = segment2->getCanonicalInterval();
Interval interval2 = leftNeighbor2->getCanonicalInterval();
if ( interval1.intersect(interval2) && (interval2.getVMin() < interval1.getVMin()) )
shrinkRight = true;
}
}
}
if ( _segment->isLocal() and segment2->isLocal() ) {
if ( shrinkLeft and shrinkRight ) {
Interval interval1 = segment2->getCanonicalInterval();
if ( toFree.getCenter() < interval1.getCenter() ) shrinkRight = false;
else shrinkLeft = false;
}
}
cdebug_log(159,0) << "- Hard overlap/enclosure/shrink " << segment2 << endl;
if ( _segment->isStrap() and segment2->isGlobal() ) continue;
if ( not (success = Manipulator(segment2,_fsm).ripup(SegmentAction::OtherRipup)) )
continue;
canonicals.clear ();
for( TrackElement* segment3
: segment2->getPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) {
DataNegociate* data3 = segment3->getDataNegociate();
if ( not data3 ) continue;
RoutingEvent* event3 = data3->getRoutingEvent();
if ( not event3 ) continue;
if ( not toFree.intersect(event3->getConstraints()) ) {
cdebug_log(159,0) << " . " << segment3 << endl;
continue;
}
cdebug_log(159,0) << " | " << segment3 << endl;
if ( shrinkRight xor shrinkLeft ) {
if ( shrinkRight ) {
if ( not (success=Manipulator(segment3,_fsm)
.ripup( SegmentAction::OtherRipupPerpandAndPushAside
, toFree.getVMin() - getPPitch()/2
)) )
break;
if ( event3->getTracksFree() == 1 ) {
cdebug_log(159,0) << "Potential left intrication with other perpandicular." << endl;
if ( segment3->getAxis() == segment2->getTargetU() - Session::getExtensionCap(getLayer()) ) {
leftIntrication = true;
leftAxisHint = segment3->getAxis();
}
}
}
if ( shrinkLeft ) {
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
cdebug_log(159,0) << "Move PP to right: "
<< DbU::getValueString(toFree.getVMax()) << " + "
<< DbU::getValueString(getPPitch()/2)
<< endl;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
if ( not (success=Manipulator(segment3,_fsm)
.ripup( SegmentAction::OtherRipupPerpandAndPushAside
, toFree.getVMax() + getPPitch()/2
)) )
break;
if ( event3->getTracksFree() == 1 ) {
cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl;
if ( segment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap(getLayer()) ) {
rightIntrication = true;
rightAxisHint = segment3->getAxis();
}
}
}
} else {
if ( not (success=Manipulator(segment3,_fsm).ripup( SegmentAction::OtherRipup
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
| SegmentAction::EventLevel3 )) )
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
break;
}
}
if ( not success ) break;
}
if ( success ) {
cdebug_log(159,0) << "Manipulator::insertInTrack() success" << endl;
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
_fsm.setState ( SegmentFsm::OtherRipup );
_fsm.addAction( _segment
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis|SegmentAction::EventLevel4
, _fsm.getCost(itrack).getTrack()->getAxis() );
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
unsigned int flags = 0;
if ( rightIntrication ) flags |= RightAxisHint;
if ( leftIntrication ) flags |= LeftAxisHint;
if ( flags )
Manipulator(_segment,_fsm).shrinkToTrack(itrack,flags,leftAxisHint,rightAxisHint);
} else
_fsm.clearActions ();
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
cdebug_tabw(159,-1);
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
return success;
}
bool Manipulator::forceToTrack ( size_t itrack )
{
Track* track = _fsm.getTrack(itrack);
size_t begin = _fsm.getBegin(itrack);
size_t end = _fsm.getEnd (itrack);
Net* ownerNet = _segment->getNet();
Interval toFree (_segment->getCanonicalInterval());
//Net* ripupNet = NULL;
set<TrackElement*> canonicals;
bool success = true;
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
cdebug_log(159,1) << "Manipulator::forceToTrack(size_t) - " << toFree << endl;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
for ( size_t i=begin ; success and (i < end) ; ++i ) {
TrackElement* segment2 = track->getSegment(i);
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if (segment2->getNet() == ownerNet) continue;
if (not toFree.intersect(segment2->getCanonicalInterval())) continue;
if (segment2->isFixed()) {
success = false;
continue;
}
//ripupNet = segment2->getNet();
DataNegociate* data2 = segment2->getDataNegociate();
if (not data2 ) {
cdebug_log(159,0) << "No DataNegociate, ignoring." << endl;
continue;
}
cdebug_log(159,0) << "- Forced ripup " << segment2 << endl;
if (not (success=Manipulator(segment2,_fsm).ripup(SegmentAction::OtherRipup)))
continue;
canonicals.clear();
for( TrackElement* segment3
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
: segment2->getPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) {
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
DataNegociate* data3 = segment3->getDataNegociate();
if (not data3) continue;
RoutingEvent* event3 = data3->getRoutingEvent();
if (not event3) continue;
if (Manipulator(segment3,_fsm).canRipup())
_fsm.addAction( segment3, SegmentAction::OtherRipup );
}
}
if (success) {
_fsm.setState ( SegmentFsm::OtherRipup );
_fsm.addAction( _segment
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis
, _fsm.getCost(itrack).getTrack()->getAxis() );
}
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
cdebug_tabw(159,-1);
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
return success;
}
bool Manipulator::shrinkToTrack ( size_t i, unsigned int flags, DbU::Unit leftAxisHint, DbU::Unit rightAxisHint )
{
#if THIS_IS_DISABLED
Track* track = _fsm.getTrack(i);
size_t begin = _fsm.getBegin(i);
size_t end = _fsm.getEnd (i);
Net* ownerNet = _segment->getNet();
set<TrackElement*> canonicals;
bool success = true;
DbU::Unit leftExtend = _segment->getSourceU() + Session::getExtensionCap(getLayer());
DbU::Unit rightExtend = _segment->getSourceU() - Session::getExtensionCap(getLayer());
cdebug_log(159,0) << "Manipulator::shrinkToTrack()" << endl;
if (_segment->isLocal()) return false;
Interval shrunkFree = _segment->base()->getMinSpanU();
cdebug_log(159,0) << "* " << shrunkFree << endl;
for ( size_t i = begin ; success and (i < end) ; ++i ) {
TrackElement* segment2 = track->getSegment(i);
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if (segment2->getNet() == ownerNet) continue;
if (segment2->isFixed()) { success = false; continue; }
if (not shrunkFree.intersect(segment2->getCanonicalInterval())) continue;
success = false;
}
if (success) {
set<TrackElement*> perpandiculars;
set<TrackElement*>::iterator iperpand;
DbU::Unit axisHint;
if (not (flags & LeftAxisHint )) leftAxisHint = shrunkFree.getCenter();
if (not (flags & RightAxisHint)) rightAxisHint = shrunkFree.getCenter();
_segment->getPerpandicularsBound( perpandiculars );
for ( iperpand = perpandiculars.begin() ; iperpand != perpandiculars.end() ; ++iperpand ) {
DataNegociate* data2 = (*iperpand)->getDataNegociate();
if (data2) {
cdebug_log(159,0) << "| perpandicular bound:" << *iperpand << endl;
success = Manipulator(*iperpand,_fsm).ripup( SegmentAction::SelfRipupPerpandWithAxisHint );
if (success) {
if ((*iperpand)->getAxis() == leftExtend ) axisHint = leftAxisHint;
else if ((*iperpand)->getAxis() == rightExtend) axisHint = rightAxisHint;
else {
cinfo << "[INFO] Bound Axis is neither left nor right\n " << (*iperpand) << endl;
axisHint = shrunkFree.getCenter();
}
_fsm.getActions()[_fsm.getActions().size()-1].setAxisHint( axisHint );
}
}
}
_fsm.addAction( _segment, SegmentAction::SelfInsert );
_fsm.setState ( SegmentFsm::OtherRipup );
cdebug_log(159,0) << "Successful shrinkToTrack." << endl;
return true;
}
#endif
return false;
}
bool Manipulator::forceOverLocals ()
{
cdebug_log(159,1) << "Manipulator::forceOverLocals()" << endl;
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
vector< array<TrackCost,2> >& costs = _fsm.getCosts();
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
size_t itrack = 0;
for ( ; itrack<costs.size() ; ++itrack ) {
cdebug_log(159,0) << "Trying itrack:" << itrack << endl;
Support for symmetric routing in Anabatic/Katabatic. * New: In Katana::SegmentFsm, the object is now able to handle two events at the same time. The master and it's symmetric. When there is no symmetric, the corresponing data is just left blank. This makes a bigger object, but as there is only one when running, it is not an issue. Candidates tracks are now an vector of array<2> (pairs), the TrackCost::Compare() functor has to be wrapped through CompareCostArray. The compined TrackCost of the two tracks is accumulated into the first element. Everything related to events gets duplicated: _event is now _event1 and _event2, and so on. As there can be now two Manipulator actions done with SegmentFsm, this class now completly hide the Manipulator level from the RoutingEvent processing. New function ::bindToTrack() to perform the track insertion. * New: In Katana::TrackCost, add a new ::merge() function. * New: In Katana::TrackElement and Katana::TrackSegment, add symmetric management. Allows to know if a TrackElement has a symmetric and to access it. * New: In Katana::DataSymmetric, add new overload for ::getSymmetrical() to handle DbU::Unit and intervals. * Change: In Katana::RoutingEvent, remove all direct uses of Manipulator objects. Now any change to the event associated segment must go through call to Segment Fsm. * Change: In Katana, adjust the debug level so internal informations are put below level 156. * New: In Hurricane::DbU, in ::getValueString(), special display when the value is Min or Max (more helpful than a gigantic number).
2017-04-30 16:46:33 -05:00
if ( costs[itrack][0].isFixed()
or costs[itrack][0].isBlockage()
or costs[itrack][0].isInfinite()
or costs[itrack][0].isOverlapGlobal() )
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
continue;
bool success = true;
Track* track = _fsm.getTrack(itrack);
size_t begin = _fsm.getBegin(itrack);
size_t end = _fsm.getEnd (itrack);
Net* ownerNet = _segment->getNet();
Interval toFree (_segment->getCanonicalInterval());
for ( size_t i = begin ; success and (i < end) ; i++ ) {
TrackElement* segment2 = track->getSegment(i);
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if ( segment2->getNet() == ownerNet ) continue;
if ( not toFree.intersect(segment2->getCanonicalInterval()) ) continue;
if ( segment2->isFixed() ) {
success = false;
continue;
}
DataNegociate* data2 = segment2->getDataNegociate();
if ( not data2 ) {
cdebug_log(159,0) << "No DataNegociate, ignoring." << endl;
success = false;
continue;
}
cdebug_log(159,0) << "- Forced ripup " << segment2 << endl;
if ( not (success=Manipulator(segment2,_fsm).ripup(SegmentAction::OtherRipup)) ) {
continue;
}
}
if (success) {
_fsm.setState ( SegmentFsm::OtherRipup );
_fsm.addAction( _segment
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis
, _fsm.getCost(itrack).getTrack()->getAxis()
);
break;
}
}
cdebug_tabw(159,-1);
return (itrack < costs.size());
}
bool Manipulator::slacken ( unsigned int flags )
{
cdebug_log(159,0) << "Manipulator::slacken() " << _segment << endl;
if ( _segment->isFixed ()) return false;
if (not _segment->canSlacken()) return false;
return _segment->slacken( flags );
}
bool Manipulator::ripple ()
{
cdebug_log(159,0) << "Manipulator::ripple() from " << _segment << endl;
//if (not _segment->canRipple()) return false;
if (not _segment->isLocal()) return false;
Net* net = _segment->getNet();
Interval uside = _segment->base()->getAutoSource()->getGCell()->getSide ( Anabatic::perpandicularTo(_segment->getDirection())/*, false*/ );
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_segment->getLayer());
cdebug_tabw(159,1);
for( Track* track : Tracks_Range::get(plane,uside)) {
size_t begin;
size_t end;
track->getOverlapBounds( _segment->getCanonicalInterval(), begin, end );
for ( ; begin < end ; begin++ ) {
TrackElement* other = track->getSegment(begin);
cdebug_log(159,0) << "| " << other << endl;
if (other->getNet() == net) continue;
if (not other->canRipple()) continue;
DataNegociate* otherData = other->getDataNegociate();
if (not otherData) continue;
DbU::Unit shiftedAxisHint;
RoutingEvent* otherEvent = otherData->getRoutingEvent();
if (other->getAxis() < _segment->getAxis()) {
// Ugly: routing pitch.
shiftedAxisHint = otherEvent->getAxisHint() - getPitch();
if (shiftedAxisHint < uside.getVMin())
shiftedAxisHint = uside.getVMin();
} else {
// Ugly: routing pitch.
shiftedAxisHint = otherEvent->getAxisHint() + getPitch();
if (shiftedAxisHint > uside.getVMax())
shiftedAxisHint = uside.getVMax();
}
otherEvent->setAxisHint( shiftedAxisHint );
_fsm.addAction( other, SegmentAction::OtherRipup );
}
}
cdebug_tabw(159,-1);
return true;
}
bool Manipulator::pivotUp ()
{
cdebug_log(159,0) << "Manipulator::pivotUp() " << _segment << endl;
return false;
if (_segment->isFixed()) return false;
if (_segment->isStrap()) return false;
float reserve = (_segment->isLocal()) ? 0.5 : 1.0;
if (not _segment->canMoveUp(reserve)) return false;
return _segment->moveUp( Flags::NoFlags );
}
bool Manipulator::pivotDown ()
{
cdebug_log(159,0) << "Manipulator::pivotDown() " << _segment << endl;
return false;
Forgot to perform Track re-order after removing zero-length segments. * Change: In Anabatic::Autocontact, replace getMinDepth() and getMaxDepth() by getDepthSpan(). * New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of low up density (Flags::CheckLowUpDensity). Allows to move up a segment if the up density is (very) low, and in this case it's more efficient than breaking it to fit in the lower layer. canMoveUp() is now able to perform the same work as canPivotUp() if *not* supplied the flag Flags::IgnoreContacts. * New: In Katana, in GlobalRouting::DigitalDistance() now take into account the cost of a VIA (currently set to 2.5). Need to known the Net currently routed in the DigitalDistance object itself. * Change: In Katana::Track::Element::canPivotUp(), now also takes a flag parameter. * Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the one of Anabatic. * Change: In Katana::SegmentFsm, allocate once a Manipulator object instead of many times on the fly. In SegmentFsm::_slackenGlobal(), in the slacken state, if the up density is (very) low, bypass to move up instead of slackening. This solve better the routing of the control part of the register file. The register file having a pathological case of terminal placement: many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and METAL3 blockages near below... * Bug: In Katana::Session::_revalidate(), after removing the zero-length segments, forgot to re-order the track, leading to many stranges effects as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
if ( _segment->isFixed () ) return false;
if ( _segment->isStrap () ) return false;
if (not _segment->canPivotDown(2.0,Flags::NoFlags)) return false;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
return _segment->moveDown( Flags::NoFlags );
}
bool Manipulator::moveUp ( unsigned int flags )
{
cdebug_log(159,0) << "Manipulator::moveUp() " << _segment << endl;
unsigned int kflags = Flags::WithNeighbors;
//kflags |= (flags & AllowLocalMoveUp ) ? Flags::AutoSegment::AllowLocal : 0;
Forgot to perform Track re-order after removing zero-length segments. * Change: In Anabatic::Autocontact, replace getMinDepth() and getMaxDepth() by getDepthSpan(). * New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of low up density (Flags::CheckLowUpDensity). Allows to move up a segment if the up density is (very) low, and in this case it's more efficient than breaking it to fit in the lower layer. canMoveUp() is now able to perform the same work as canPivotUp() if *not* supplied the flag Flags::IgnoreContacts. * New: In Katana, in GlobalRouting::DigitalDistance() now take into account the cost of a VIA (currently set to 2.5). Need to known the Net currently routed in the DigitalDistance object itself. * Change: In Katana::Track::Element::canPivotUp(), now also takes a flag parameter. * Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the one of Anabatic. * Change: In Katana::SegmentFsm, allocate once a Manipulator object instead of many times on the fly. In SegmentFsm::_slackenGlobal(), in the slacken state, if the up density is (very) low, bypass to move up instead of slackening. This solve better the routing of the control part of the register file. The register file having a pathological case of terminal placement: many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and METAL3 blockages near below... * Bug: In Katana::Session::_revalidate(), after removing the zero-length segments, forgot to re-order the track, leading to many stranges effects as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
kflags |= (flags & AllowTerminalMoveUp) ? Flags::AllowTerminal : 0;
kflags |= (flags & IgnoreContacts ) ? Flags::IgnoreContacts : 0;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
if (_segment->isFixed()) return false;
if (not (flags & AllowLocalMoveUp)) {
if (_segment->isLocal()) {
Forgot to perform Track re-order after removing zero-length segments. * Change: In Anabatic::Autocontact, replace getMinDepth() and getMaxDepth() by getDepthSpan(). * New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of low up density (Flags::CheckLowUpDensity). Allows to move up a segment if the up density is (very) low, and in this case it's more efficient than breaking it to fit in the lower layer. canMoveUp() is now able to perform the same work as canPivotUp() if *not* supplied the flag Flags::IgnoreContacts. * New: In Katana, in GlobalRouting::DigitalDistance() now take into account the cost of a VIA (currently set to 2.5). Need to known the Net currently routed in the DigitalDistance object itself. * Change: In Katana::Track::Element::canPivotUp(), now also takes a flag parameter. * Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the one of Anabatic. * Change: In Katana::SegmentFsm, allocate once a Manipulator object instead of many times on the fly. In SegmentFsm::_slackenGlobal(), in the slacken state, if the up density is (very) low, bypass to move up instead of slackening. This solve better the routing of the control part of the register file. The register file having a pathological case of terminal placement: many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and METAL3 blockages near below... * Bug: In Katana::Session::_revalidate(), after removing the zero-length segments, forgot to re-order the track, leading to many stranges effects as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
if (not _segment->canPivotUp(0.5,kflags)) return false;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
} else {
if (_segment->getLength() < 20*getPitch()) {
if (not (flags & AllowShortPivotUp)) return false;
Forgot to perform Track re-order after removing zero-length segments. * Change: In Anabatic::Autocontact, replace getMinDepth() and getMaxDepth() by getDepthSpan(). * New: In Anabatic::AutoSegment::canMoveUp(), add an optional check of low up density (Flags::CheckLowUpDensity). Allows to move up a segment if the up density is (very) low, and in this case it's more efficient than breaking it to fit in the lower layer. canMoveUp() is now able to perform the same work as canPivotUp() if *not* supplied the flag Flags::IgnoreContacts. * New: In Katana, in GlobalRouting::DigitalDistance() now take into account the cost of a VIA (currently set to 2.5). Need to known the Net currently routed in the DigitalDistance object itself. * Change: In Katana::Track::Element::canPivotUp(), now also takes a flag parameter. * Change: In Katana::Manipulator, new flag IgnoreContacts to mirror the one of Anabatic. * Change: In Katana::SegmentFsm, allocate once a Manipulator object instead of many times on the fly. In SegmentFsm::_slackenGlobal(), in the slacken state, if the up density is (very) low, bypass to move up instead of slackening. This solve better the routing of the control part of the register file. The register file having a pathological case of terminal placement: many punctual terminals aligneds in METAL2 *and* a grid of METAL2 and METAL3 blockages near below... * Bug: In Katana::Session::_revalidate(), after removing the zero-length segments, forgot to re-order the track, leading to many stranges effects as the indexes where no longer coherent in the Track.
2016-09-20 04:30:45 -05:00
if (not _segment->canPivotUp(1.0,kflags)) return false;
Anabatic transient commit 18. Port of Kite (Katana), Yeah, Baby! Yeah! * Bug: In Hurricane, in StaticObservable::getObserver(), if the slot pointer is NULL, do not try to access the owner. Returns NULL, so the caller can be aware of the situation... * Change: In Hurricane, in BreakpointWidget & ExceptionWidget some cosmetic changes (fonts and window sizes). * Bug: In Anabatic, In AutoHorizontal::getConstraints(), take into account the constraints from the source AutoContact, as it holds the constraints transmitted by the RoutingPads and sets up by propageConstraintsFromRp(). It is likely to be a bug affecting the original Katabatic as well. * Change: In Anabatic, in RawGCellsUnder(), check that the segment is not completly oustside the cell abutment box and truncate the coordinates to the part that is inside. Use the "shrink" if we reach the east/north border. * Change: In Anabatic, in Configuration, no more decorator because we will use a true derived relationship. Katana *derives* from *Anabatic* and do not *decorate* it, so the Configuration can do the same. It also implies that we directly create a Katana engine, not an Anabatic one. * Change: In Anabatic, in Session, do not allow the opening of the Session in a standalone fashion (with a static method). Instead it must be opened using the relevant method of the Anabatic/Katana engine. This ensure we are opening the right Session type. * Change: In Anabatic, in AutoSegment_Aligneds() collection the seed segment is not part of the collection by default, but will be included if the Flags::WithSelf is set. * Change: In Configuration, all the flags value are now defined in two steps. Declared in the header and initialized in the module. This is to prevent the fact that on some cases, in relation with the Python "extern C" part modules, we need a true allocated variable. It was causing weird linking problems. A side effect is that they can no longer be used as entry is switches, have to replace them by if/else. * New: In Anabatic, new GCell::getNeighborAt() utility function. * Bug: In Anabatic, in GCell::doGrid(), tag all the GCells of the grid with the grid type... Back annote all the edges capacity (north & east) with the reserved local capacity. * New: Complete portage of Kite over Anabatic. The new engine is christened "Katana" for Kite-Analogic. When it's capabilities and performances will be on a part with Kite, it is to completly replace it (and take back the "Kite" name). Preliminary tests seems to show that, contrary to intuition (because built on a more complex/slower grid), it is even slightly faster than Kite 8-).
2016-08-15 09:30:13 -05:00
}
if (not _segment->canMoveUp(0.5,kflags)) return false;
}
} else {
if (not _segment->canMoveUp(0.5,kflags)) return false;
}
return _segment->moveUp( kflags );
}
bool Manipulator::makeDogleg ()
{
cdebug_log(159,0) << "Manipulator::makeDogleg() " << _segment << endl;
if ( _segment->isFixed()) return false;
if (not _segment->isLocal()) return false;
if (_segment->getLength() < 5*getPitch()) return false;
if (_fsm.getCosts().size()) {
Track* track = _fsm.getTrack(0);
size_t begin = _fsm.getBegin(0);
size_t end = _fsm.getEnd (0);
Net* ownerNet = _segment->getNet();
Interval toFree (_segment->getCanonicalInterval());
Interval overlap;
for ( size_t i=begin ; i<end ; ++i ) {
TrackElement* segment2 = track->getSegment(i);
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if ( segment2->getNet() == ownerNet) continue;
if (not toFree.intersect(segment2->getCanonicalInterval())) continue;
if (overlap.isEmpty())
overlap = segment2->getCanonicalInterval();
else
overlap.merge( segment2->getCanonicalInterval() );
}
if (not overlap.isEmpty() and makeDogleg(overlap)) return true;
}
if (not _segment->canDogleg()) return false;
_segment->makeDogleg();
return true;
}
bool Manipulator::makeDogleg ( Interval overlap )
{
cdebug_log(159,0) << "Manipulator::makeDogleg(Interval) " << _segment << endl;
cdebug_log(159,0) << overlap << endl;
if ( _segment->isFixed () ) return false;
if (not _segment->canDogleg(overlap)) return false;
unsigned int flags = 0;
TrackElement* dogleg = _segment->makeDogleg(overlap,flags);
if (dogleg) {
cdebug_log(159,0) << "Manipulator::makeDogleg(Interval) - Push dogleg to the "
<< ((flags&Flags::DoglegOnLeft)?"left":"right") << endl;
if (_segment->isTerminal()) {
Anabatic::AutoContact* contact =
(flags&Flags::DoglegOnLeft) ? _segment->base()->getAutoSource()
: _segment->base()->getAutoTarget();
DbU::Unit axisHint = (_segment->isHorizontal()) ? contact->getX() : contact->getY();
RoutingEvent* event = dogleg->getDataNegociate()->getRoutingEvent();
if (event) {
event->setAxisHint ( axisHint );
event->setForcedToHint( true );
cdebug_log(159,0) << "Forced to axis hint @" << DbU::getValueString(axisHint) << endl;
}
}
return true;
}
return false;
}
bool Manipulator::makeDogleg ( DbU::Unit position )
{
cdebug_log(159,0) << "Manipulator::makeDogleg(position) " << _segment << endl;
cdebug_log(159,0) << "Breaking position: " << DbU::getValueString(position) << endl;
if (_segment->isFixed()) return false;
vector<GCell*> gcells;
_segment->getGCells( gcells );
size_t igcell = 0;
for ( ; igcell<gcells.size() ; igcell++ ) {
if (gcells[igcell]->getSide(_segment->getDirection()).contains(position))
break;
}
if (igcell == gcells.size()) return false;
if (not _segment->canDogleg(gcells[igcell])) return false;
TrackElement* dogleg = NULL;
TrackElement* parallel = NULL;
_segment->makeDogleg( gcells[igcell], dogleg, parallel );
return (dogleg != NULL);
}
bool Manipulator::minimize ()
{
cdebug_log(159,0) << "Manipulator::minimize() " << _segment << endl;
if (_segment->isFixed()) return false;
if (not _event->canMinimize()) return false;
DbU::Unit minSpan = DbU::Max;
DbU::Unit maxSpan = DbU::Min;
Interval punctualSpan ( false );
if (_segment->base()->getAutoSource()->getAnchor()) {
cdebug_log(159,0) << " | " << _segment->base()->getAutoSource() << endl;
Interval constraints ( _segment->base()->getAutoSource()->getUConstraints
(perpandicularTo(_segment->getDirection())) );
cdebug_log(159,0) << " | Constraints: " << constraints << endl;
minSpan = min( minSpan, constraints.getVMax() );
maxSpan = max( maxSpan, constraints.getVMin() );
punctualSpan.intersection( constraints );
}
if (_segment->base()->getAutoTarget()->getAnchor()) {
cdebug_log(159,0) << " | " << _segment->base()->getAutoTarget() << endl;
Interval constraints ( _segment->base()->getAutoTarget()->getUConstraints
(perpandicularTo(_segment->getDirection())) );
cdebug_log(159,0) << " | Constraints: " << constraints << endl;
minSpan = min( minSpan, constraints.getVMax() );
maxSpan = max( maxSpan, constraints.getVMin() );
punctualSpan.intersection( constraints );
}
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
for ( size_t i=0 ; i<perpandiculars.size() ; i++ ) {
DataNegociate* data2 = perpandiculars[i]->getDataNegociate();
if (not data2) continue;
cdebug_log(159,0) << " | " << perpandiculars[i] << endl;
RoutingEvent* event2 = data2->getRoutingEvent();
if (not event2) continue;
cdebug_log(159,0) << " | Constraints: " << event2->getConstraints() << endl;
minSpan = min( minSpan, event2->getConstraints().getVMax() );
maxSpan = max( maxSpan, event2->getConstraints().getVMin() );
punctualSpan.intersection( event2->getConstraints() );
}
if (minSpan > maxSpan) swap( minSpan, maxSpan );
cdebug_log(159,0) << "punctualSpan: " << punctualSpan
<< " min/max span: [" << DbU::getValueString(minSpan)
<< ":" << DbU::getValueString(maxSpan) << "]"
<< " long: [" << minSpan
<< ":" << maxSpan << "]" << endl;
vector<Interval> holes;
for ( size_t itrack=0 ; itrack<_fsm.getCosts().size() ; itrack++ ) {
size_t begin = _fsm.getBegin(itrack);
size_t end = _fsm.getEnd (itrack);
Track* track = _fsm.getTrack(itrack);
if (end < track->getSize()) end++;
cdebug_log(159,0) << "Looking for holes in " << _fsm.getCost(itrack) << endl;
TrackElement* otherPrevious = NULL;
// ToDo: Manage disjoint but subsequent segment of a Net.
// (currently, that hole will not be found).
for ( ; begin < end ; begin++ ) {
TrackElement* otherSegment = track->getSegment(begin);
if (otherSegment->getNet() == _segment->getNet()) continue;
if (not otherPrevious) {
holes.push_back( Interval(track->getMin()
,otherSegment->getSourceU()) );
cdebug_log(159,0) << "| First hole: " << holes.back() << " " << otherSegment << endl;
} else {
if (otherSegment->getNet() == otherPrevious->getNet()) continue;
holes.push_back( Interval(otherPrevious->getTargetU()
,otherSegment ->getSourceU()) );
cdebug_log(159,0) << "| Found hole: " << holes.back()
<< " " << otherPrevious << " <-> " << " " << otherSegment << endl;
}
otherPrevious = otherSegment;
}
}
if (holes.empty()) {
cdebug_log(159,0) << "No holes found to minimize into." << endl;
return false;
}
Interval currentSpan = _segment->getCanonicalInterval();
Interval biggestHole;
for ( size_t i=0 ; i<holes.size() ; i++ ) {
if ( currentSpan.getIntersection(holes[i] ).getSize()
> currentSpan.getIntersection(biggestHole).getSize() )
biggestHole = holes[i];
}
DbU::Unit axisHint = 0;
if (not punctualSpan.isEmpty()) {
bool success = false;
if (biggestHole.intersect(punctualSpan)) {
cdebug_log(159,0) << "Go as punctual into biggest hole: " << biggestHole << endl;
axisHint = biggestHole.intersection(punctualSpan).getCenter();
success = true;
} else {
for ( size_t i=0 ; i<holes.size() ; i++ ) {
cdebug_log(159,0) << "Trying secondary hole: " << holes[i] << endl;
if (holes[i].intersect(punctualSpan)) {
biggestHole = holes[i];
axisHint = biggestHole.intersection(punctualSpan).getCenter();
cdebug_log(159,0) << "Go as punctual into secondary hole: " << biggestHole << endl;
success = true;
}
}
}
if (not success) {
cdebug_log(159,0) << "No suitable hole found." << endl;
return false;
}
} else {
biggestHole.intersection( Interval(minSpan,maxSpan) );
if (biggestHole.isEmpty()) {
cdebug_log(159,0) << "Biggest hole is empty (under span ["
<< DbU::getValueString(minSpan) << " "
<< DbU::getValueString(maxSpan) << "])" << endl;
return false;
} else {
cdebug_log(159,0) << "Go into biggest hole: " << biggestHole << endl;
axisHint = biggestHole.getCenter();
}
}
cdebug_log(159,0) << "Axis Hint: " << DbU::getValueString(axisHint) << endl;
for ( size_t i=0 ; i<perpandiculars.size() ; i++ ) {
DataNegociate* data2 = perpandiculars[i]->getDataNegociate();
if (not data2) continue;
cdebug_log(159,0) << " | " << perpandiculars[i] << endl;
RoutingEvent* event2 = data2->getRoutingEvent();
if (not event2) continue;
_fsm.addAction( perpandiculars[i], SegmentAction::SelfRipupPerpandWithAxisHint, axisHint );
}
_event->setMinimized();
return true;
}
void Manipulator::reprocessPerpandiculars ()
{
if ( _event->getAxisHistory() == _event->getAxisHint() ) return;
bool moveLeft = (_event->getAxisHistory() > _event->getAxisHint());
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
TrackElement* perpandicular = perpandiculars[iperpand];
DataNegociate* data = perpandicular->getDataNegociate();
if ( perpandicular->isFixed() ) continue;
if ( not data ) continue;
if ( not perpandicular->getTrack() ) continue;
if ( not Manipulator(perpandicular,_fsm).canRipup()
or (data->getState() >= DataNegociate::MaximumSlack) ) continue;
// Ugly: ExtensionCap usage.
if ( moveLeft ) {
if ( perpandicular->getTargetU()-Session::getExtensionCap(getLayer()) == _event->getAxisHistory() )
_fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking );
} else {
if ( perpandicular->getSourceU()+Session::getExtensionCap(getLayer()) == _event->getAxisHistory() )
_fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking );
}
}
}
void Manipulator::repackPerpandiculars ()
{
cdebug_log(159,0) << "Manipulator::repackPerpandiculars()" << endl;
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
TrackElement* perpandicular = perpandiculars[iperpand];
DataNegociate* data = perpandicular->getDataNegociate();
if (perpandicular->isFixed ()) continue;
if (perpandicular->isGlobal()) continue;
if (not data) continue;
if (RoutingEvent::getStage() == RoutingEvent::Repair) {
data->setState( DataNegociate::Repair );
if (data->getStateCount() > 1) data->resetStateCount();
}
_fsm.addAction( perpandicular, SegmentAction::SelfRipupPerpand );
}
_fsm.addAction( _segment, SegmentAction::SelfRipup|SegmentAction::EventLevel4 );
}
} // Katana namespace.