2010-03-09 09:24:29 -06:00
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
// Copyright (c) UPMC 2008-2014, All Rights Reserved
|
2010-03-09 09:24:29 -06:00
|
|
|
//
|
2012-12-03 02:28:43 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:29 -06:00
|
|
|
// | C O R I O L I S |
|
|
|
|
// | K a t a b a t i c - Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
2013-12-03 18:58:58 -06:00
|
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
2010-03-09 09:24:29 -06:00
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./AutoSegment.cpp" |
|
2012-12-03 02:28:43 -06:00
|
|
|
// +-----------------------------------------------------------------+
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/DataBase.h"
|
|
|
|
#include "hurricane/Technology.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "crlcore/RoutingGauge.h"
|
|
|
|
#include "katabatic/Session.h"
|
|
|
|
#include "katabatic/AutoContact.h"
|
|
|
|
#include "katabatic/AutoSegment.h"
|
|
|
|
#include "katabatic/AutoHorizontal.h"
|
|
|
|
#include "katabatic/AutoVertical.h"
|
|
|
|
#include "katabatic/GCell.h"
|
|
|
|
#include "katabatic/KatabaticEngine.h"
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace CRL;
|
|
|
|
using namespace Hurricane;
|
|
|
|
using namespace Katabatic;
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
|
|
// Local Variables.
|
|
|
|
|
|
|
|
|
|
|
|
const char* badAutoSegmentAnchor =
|
|
|
|
"AutoSegment::create() :\n\n"
|
|
|
|
" Source and/or target anchor is NOT an <AutoContact> (internal error).\n"
|
|
|
|
" Source: %s, Target: %s";
|
|
|
|
|
|
|
|
const char* dupAutoSegmentAnchor =
|
|
|
|
"AutoSegment::create() :\n\n"
|
|
|
|
" Source and Target anchor are the same : %s (internal error).";
|
|
|
|
|
|
|
|
const char* badSegment =
|
|
|
|
"Katabatic::AutoSegment::create () :\n\n"
|
|
|
|
" Segment between %s and %s\n"
|
|
|
|
" is neither horizontal nor vertical .\n";
|
|
|
|
|
|
|
|
const char* badSegmentSource =
|
|
|
|
"Katabatic::AutoSegment::create () :\n\n"
|
|
|
|
" Source anchor of segment %s is not a Contact\n"
|
|
|
|
" (%s)\n";
|
|
|
|
|
|
|
|
const char* badSegmentTarget =
|
|
|
|
"Katabatic::AutoSegment::create () :\n\n"
|
|
|
|
" Source anchor of segment %s is not a Contact\n"
|
|
|
|
" (%s)\n";
|
|
|
|
|
|
|
|
const char* mismatchSegmentSource =
|
|
|
|
"Katabatic::AutoSegment::create () :\n\n"
|
|
|
|
" Source anchor of segment %s is already an AutoContact\n"
|
|
|
|
" (%s)\n";
|
|
|
|
|
|
|
|
const char* mismatchSegmentTarget =
|
|
|
|
"Katabatic::AutoSegment::create () :\n\n"
|
|
|
|
" Target anchor of segment %s is already an AutoContact\n"
|
|
|
|
" (%s)\n";
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
|
|
// Local Functions.
|
|
|
|
|
|
|
|
|
|
|
|
bool getTerminalInterval ( AutoSegment* autoSegment
|
|
|
|
, AutoContact* fromContact
|
|
|
|
, bool isHorizontal
|
|
|
|
, DbU::Unit& min
|
|
|
|
, DbU::Unit& max
|
|
|
|
)
|
|
|
|
{
|
|
|
|
AutoContact* terminalContact = NULL;
|
|
|
|
|
|
|
|
if ( !fromContact ) {
|
|
|
|
bool found = getTerminalInterval ( autoSegment
|
|
|
|
, autoSegment->getAutoSource()
|
|
|
|
, autoSegment->isHorizontal()
|
|
|
|
, min
|
|
|
|
, max );
|
|
|
|
if ( !found )
|
|
|
|
found = getTerminalInterval ( autoSegment
|
|
|
|
, autoSegment->getAutoTarget()
|
|
|
|
, autoSegment->isHorizontal()
|
|
|
|
, min
|
|
|
|
, max );
|
|
|
|
|
|
|
|
//if ( !found )
|
|
|
|
// cerr << "[ERROR] Cannot find terminal of " << autoSegment << "." << endl;
|
|
|
|
|
|
|
|
return found;
|
|
|
|
} else {
|
|
|
|
if ( autoSegment->isGlobal() ) return false;
|
|
|
|
|
|
|
|
ltrace(88) << "Examining " << autoSegment << " " << fromContact << endl;
|
|
|
|
|
|
|
|
if ( autoSegment->getSource() == autoSegment->getTarget() ) {
|
|
|
|
cerr << Error("Source & Target are the same :\n"
|
|
|
|
" %s\n %s"
|
|
|
|
,getString(autoSegment).c_str()
|
|
|
|
,getString(autoSegment->getSource()).c_str()) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
terminalContact = autoSegment->getAutoSource();
|
|
|
|
if ( terminalContact == fromContact ) {
|
|
|
|
terminalContact = autoSegment->getAutoTarget();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !terminalContact->isTerminal() ) {
|
|
|
|
AutoSegment* segment = NULL;
|
|
|
|
size_t segmentCount = 0;
|
|
|
|
forEach ( Component*, icomponent, terminalContact->getSlaveComponents() ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( *icomponent == autoSegment->base() ) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
Segment* connex = dynamic_cast<Segment*>(*icomponent);
|
|
|
|
if ( !connex ) continue;
|
|
|
|
|
|
|
|
segment = Session::lookup ( connex );
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( not segment or not segment->isWeakTerminal() ) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
segmentCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( segmentCount == 1 ) {
|
|
|
|
return getTerminalInterval ( segment, terminalContact, isHorizontal, min, max );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ltrace(88) << "Terminal is " << terminalContact << endl;
|
|
|
|
|
|
|
|
Box constraintBox = terminalContact->getConstraintBox();
|
|
|
|
if ( isHorizontal ) {
|
|
|
|
min = constraintBox.getXMin ();
|
|
|
|
max = constraintBox.getXMax ();
|
|
|
|
} else {
|
|
|
|
min = constraintBox.getYMin ();
|
|
|
|
max = constraintBox.getYMax ();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------
|
|
|
|
// Class : "AttractorsMap".
|
|
|
|
|
|
|
|
|
|
|
|
class AttractorsMap {
|
|
|
|
// Constructor.
|
|
|
|
public:
|
|
|
|
inline AttractorsMap ();
|
|
|
|
inline size_t getAttractorsCount () const;
|
|
|
|
DbU::Unit getLowerMedian () const;
|
|
|
|
DbU::Unit getUpperMedian () const;
|
|
|
|
void addAttractor ( DbU::Unit position );
|
|
|
|
protected:
|
|
|
|
map<DbU::Unit,size_t> _attractors;
|
|
|
|
size_t _attractorsCount;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
inline AttractorsMap::AttractorsMap ()
|
|
|
|
: _attractors(), _attractorsCount(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
inline size_t AttractorsMap::getAttractorsCount () const
|
|
|
|
{
|
|
|
|
return _attractorsCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AttractorsMap::addAttractor ( DbU::Unit position )
|
|
|
|
{
|
|
|
|
_attractors[position]++;
|
|
|
|
_attractorsCount++;
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
ltrace(88) << "add Attractor @" << DbU::toLambda(position)
|
2010-03-09 09:24:29 -06:00
|
|
|
<< " [" << _attractors[position] << "]" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit AttractorsMap::getLowerMedian () const
|
|
|
|
{
|
|
|
|
size_t median = (_attractorsCount/2) + (_attractorsCount%2);
|
|
|
|
size_t lower = 0;
|
|
|
|
|
|
|
|
map<DbU::Unit,size_t>::const_iterator it = _attractors.begin ();
|
|
|
|
for ( ; it != _attractors.end() ; it++ ) {
|
|
|
|
lower += it->second;
|
|
|
|
if ( lower >= median ) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return it->first;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit AttractorsMap::getUpperMedian () const
|
|
|
|
{
|
|
|
|
size_t median = _attractorsCount / 2;
|
|
|
|
size_t upper = 0;
|
|
|
|
|
|
|
|
map<DbU::Unit,size_t>::const_iterator it = _attractors.begin ();
|
|
|
|
for ( ; it != _attractors.end() ; it++ ) {
|
|
|
|
upper += it->second;
|
|
|
|
if ( upper > median ) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return it->first;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // End of local namespace.
|
|
|
|
|
|
|
|
|
|
|
|
namespace Katabatic {
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
// Class : "Katabatic::AutoSegment::CompareByDepthLength".
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
bool AutoSegment::CompareByDepthLength::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
int deltaDepth = (int)(Session::getRoutingGauge()->getLayerDepth(lhs->getLayer()))
|
|
|
|
- (int)(Session::getRoutingGauge()->getLayerDepth(rhs->getLayer()));
|
|
|
|
if ( deltaDepth < 0 ) return true; // Lowest layer first.
|
|
|
|
if ( deltaDepth > 0 ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
DbU::Unit deltaUnit = lhs->getSourceU() - rhs->getSourceU();
|
|
|
|
if ( deltaUnit < 0 ) return true; // Smallest source first.
|
|
|
|
if ( deltaUnit > 0 ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
deltaUnit = lhs->getLength() - rhs->getLength();
|
|
|
|
if ( deltaUnit > 0 ) return true; // Longest first.
|
|
|
|
if ( deltaUnit < 0 ) return true;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
deltaUnit = lhs->getAxis() - rhs->getAxis();
|
|
|
|
if ( deltaUnit < 0 ) return true; // Smallest axis first.
|
|
|
|
if ( deltaUnit > 0 ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
// if ( lhs->isCanonical () xor rhs->isCanonical () ) return lhs->isCanonical();
|
|
|
|
// if ( lhs->isCollapsed () xor rhs->isCollapsed () ) return rhs->isCollapsed();
|
|
|
|
// if ( lhs->isSlackenStrap() xor rhs->isSlackenStrap() ) return lhs->isSlackenStrap();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
// if ( lhs->isGlobal () xor rhs->isGlobal () ) return lhs->isGlobal();
|
|
|
|
// if ( lhs->isTerminal () xor rhs->isTerminal () ) return rhs->isTerminal();
|
|
|
|
// if ( lhs->isHorizontal() xor rhs->isHorizontal() ) return lhs->isHorizontal();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
// if ( lhs->isFixed() xor rhs->isFixed() ) return lhs->isFixed();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
return lhs->getId() < rhs->getId();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::AutoSegment::CompareByDepthAxis".
|
|
|
|
|
|
|
|
|
|
|
|
bool AutoSegment::CompareByDepthAxis::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
|
|
|
|
{
|
|
|
|
int deltaDepth = (int)(Session::getRoutingGauge()->getLayerDepth(lhs->getLayer()))
|
|
|
|
- (int)(Session::getRoutingGauge()->getLayerDepth(rhs->getLayer()));
|
|
|
|
if ( deltaDepth < 0 ) return true; // Lowest layer first.
|
|
|
|
if ( deltaDepth > 0 ) return false;
|
|
|
|
|
|
|
|
DbU::Unit deltaUnit = lhs->getAxis() - rhs->getAxis();
|
|
|
|
if ( deltaUnit < 0 ) return true; // Smallest axis first.
|
|
|
|
if ( deltaUnit > 0 ) return false;
|
|
|
|
|
|
|
|
deltaUnit = lhs->getSourceU() - rhs->getSourceU();
|
|
|
|
if ( deltaUnit < 0 ) return true; // Smallest source first.
|
|
|
|
if ( deltaUnit > 0 ) return false;
|
|
|
|
|
|
|
|
return lhs->getId() < rhs->getId(); // Smallest Id first.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
// -------------------------------------------------------------------
|
|
|
|
// Class : "Katabatic::AutoSegment".
|
|
|
|
|
|
|
|
|
2010-04-23 08:13:54 -05:00
|
|
|
size_t AutoSegment::_allocateds = 0;
|
|
|
|
size_t AutoSegment::_globalsCount = 0;
|
|
|
|
unsigned long AutoSegment::_maxId = 0;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegment::AutoSegment ( Segment* segment )
|
|
|
|
: _id (segment->getId())
|
|
|
|
, _flags (SegCreated)
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
, _depth (Session::getLayerDepth(segment->getLayer()))
|
2013-12-03 18:58:58 -06:00
|
|
|
, _optimalMin (0)
|
|
|
|
, _sourcePosition (0)
|
|
|
|
, _targetPosition (0)
|
|
|
|
, _userConstraints(false)
|
|
|
|
, _parent (NULL)
|
|
|
|
, _observers ()
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoContact* source = Session::lookup(dynamic_cast<Contact*>(segment->getSource()));
|
|
|
|
AutoContact* target = Session::lookup(dynamic_cast<Contact*>(segment->getTarget()));
|
|
|
|
|
|
|
|
_allocateds++;
|
|
|
|
|
|
|
|
if (dynamic_cast<Horizontal*>(segment)) setFlags( SegHorizontal );
|
|
|
|
if (source->isTerminal() or target->isTerminal()) setFlags( SegStrongTerminal );
|
|
|
|
|
|
|
|
_gcell = source->getGCell();
|
|
|
|
setOptimalMax ( isHorizontal() ? _gcell->getBoundingBox().getYMax()
|
|
|
|
: _gcell->getBoundingBox().getXMax() );
|
|
|
|
|
|
|
|
_globalsCount += isGlobal() ? 1 : 0;
|
|
|
|
|
|
|
|
source->invalidate( KbTopology );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::_preCreate ( AutoContact* source, AutoContact* target )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( (source == NULL) or (target == NULL) )
|
|
|
|
throw Error( badAutoSegmentAnchor
|
|
|
|
, ((source)?getString(source).c_str():"NULL")
|
|
|
|
, ((target)?getString(target).c_str():"NULL")
|
|
|
|
);
|
|
|
|
|
|
|
|
if (source == target)
|
|
|
|
throw Error( dupAutoSegmentAnchor, getString(source).c_str() );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::_postCreate ()
|
|
|
|
{
|
|
|
|
Session::invalidate( getNet() );
|
|
|
|
Session::link( this );
|
|
|
|
updateOrient();
|
|
|
|
updatePositions();
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
invalidate( KbTopology );
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
_observers.notify( Create );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AutoSegment::_preDestroy ()
|
|
|
|
{
|
|
|
|
ltrace(200) << "AutoSegment::_preDestroy() - " << (void*)this << endl;
|
|
|
|
ltracein(90);
|
|
|
|
|
|
|
|
_observers.notify( Destroy );
|
|
|
|
|
|
|
|
Session::unlink( this );
|
|
|
|
ltraceout(90);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegment::~AutoSegment ()
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
_allocateds--;
|
|
|
|
if ( isGlobal() and (_globalsCount > 0) ) _globalsCount--;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
DbU::Unit AutoSegment::getX () const
|
|
|
|
{ return base()->getX(); }
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit AutoSegment::getY () const
|
|
|
|
{ return base()->getY(); }
|
|
|
|
|
|
|
|
|
|
|
|
AutoContact* AutoSegment::getOppositeAnchor ( AutoContact* anchor ) const
|
|
|
|
{ return Session::lookup(static_cast<Contact*>(getOppositeAnchor(anchor->base()))); }
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
Interval& AutoSegment::getOptimal ( Interval& i ) const
|
|
|
|
{
|
|
|
|
i.getVMin() = getOptimalMin();
|
|
|
|
i.getVMax() = getOptimalMax();
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::checkNotInvalidated () const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isInvalidated())
|
2010-03-09 09:24:29 -06:00
|
|
|
cerr << Error("%s is invalidated.",getString(this).c_str()) << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return not isInvalidated();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::invalidate ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (Session::doDestroyTool()) return;
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
if (flags & KbSource) setFlags( SegInvalidatedSource );
|
|
|
|
if (flags & KbTarget) setFlags( SegInvalidatedTarget );
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isInvalidated()) return;
|
|
|
|
|
|
|
|
ltrace(200) << "AutoSegment::invalidate() " << flags << " " << this << endl;
|
|
|
|
ltracein(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_invalidate();
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
forEach( AutoSegment*, isegment, getAligneds() ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
isegment->_invalidate();
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AutoSegment::_invalidate ()
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isInvalidated()) return;
|
|
|
|
ltrace(110) << "AutoSegment::_invalidate() " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
setFlags( SegInvalidated );
|
|
|
|
Session::invalidate( this );
|
|
|
|
|
|
|
|
_observers.notify( Invalidate );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
void AutoSegment::invalidate ( AutoContact* contact )
|
|
|
|
{
|
|
|
|
if (Session::doDestroyTool()) return;
|
|
|
|
if (contact == getAutoSource()) setFlags( SegInvalidatedSource );
|
|
|
|
if (contact == getAutoTarget()) setFlags( SegInvalidatedTarget );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
void AutoSegment::revalidate ()
|
|
|
|
{
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
ltrace(200) << "AutoSegment::revalidate() " << this << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isInvalidated()) return;
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
ltracein(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
updateOrient ();
|
2013-12-03 18:58:58 -06:00
|
|
|
updatePositions();
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
unsigned int oldSpinFlags = _flags & SegDepthSpin;
|
|
|
|
|
|
|
|
if (_flags & (SegInvalidatedSource|SegCreated)) {
|
|
|
|
const Layer* contactLayer = getAutoSource()->getLayer();
|
|
|
|
const Layer* segmentLayer = getLayer();
|
|
|
|
ltrace(200) << "Changed source: " << getAutoSource() << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
unsetFlags( SegSourceTop|SegSourceBottom );
|
|
|
|
if (contactLayer != segmentLayer) {
|
|
|
|
setFlags( (segmentLayer == contactLayer->getTop()) ? SegSourceBottom : SegSourceTop );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_flags & (SegInvalidatedTarget|SegCreated)) {
|
|
|
|
const Layer* contactLayer = getAutoTarget()->getLayer();
|
|
|
|
const Layer* segmentLayer = getLayer();
|
|
|
|
ltrace(200) << "Changed target: " << getAutoTarget() << endl;
|
|
|
|
|
|
|
|
unsetFlags( SegTargetTop|SegTargetBottom );
|
|
|
|
if (contactLayer != segmentLayer) {
|
|
|
|
setFlags( (segmentLayer == contactLayer->getTop()) ? SegTargetBottom : SegTargetTop );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int observerFlags = Revalidate;
|
|
|
|
if ( (_flags & SegCreated) or (oldSpinFlags != (_flags & SegDepthSpin)) )
|
|
|
|
observerFlags |= RevalidatePPitch;
|
|
|
|
|
|
|
|
unsetFlags( SegInvalidated
|
|
|
|
| SegInvalidatedSource
|
|
|
|
| SegInvalidatedTarget
|
|
|
|
| SegInvalidatedLayer
|
|
|
|
| SegCreated
|
|
|
|
);
|
|
|
|
|
|
|
|
_observers.notify( observerFlags );
|
|
|
|
|
|
|
|
ltrace(200) << "Updated: " << this << endl;
|
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::isStrongTerminal ( unsigned int flags ) const
|
|
|
|
{
|
|
|
|
if (_flags & SegStrongTerminal) return true;
|
|
|
|
|
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) {
|
|
|
|
if (isegment->_flags & SegStrongTerminal) return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
bool AutoSegment::isSameLayerDogleg () const
|
|
|
|
{
|
|
|
|
if (not isSpinTopOrBottom()) return false;
|
|
|
|
|
|
|
|
unsigned int perpandicularDepth = getDepth() + (isSpinTop() ? 1 : -1);
|
|
|
|
if (perpandicularDepth >= Session::getDepth()) {
|
|
|
|
cerr << this << " isSpinTop too high." << endl;
|
|
|
|
}
|
|
|
|
perpandicularDepth = Session::getDepth() - 1;
|
|
|
|
|
|
|
|
return (getLength() > (Session::getPitch(perpandicularDepth)))
|
|
|
|
and (getLength() < (Session::getPitch(perpandicularDepth) * 3));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit AutoSegment::getPPitch () const
|
|
|
|
{
|
|
|
|
DbU::Unit topPPitch = getPitch();
|
|
|
|
DbU::Unit bottomPPitch = topPPitch;
|
|
|
|
unsigned int depth = getDepth();
|
|
|
|
|
|
|
|
if (depth < Session::getDepth()) {
|
|
|
|
topPPitch = Session::getPitch( depth + ((_flags & SegSpinTop) ? 1 : 0) );
|
|
|
|
}
|
|
|
|
if (depth > 0) {
|
|
|
|
bottomPPitch = Session::getPitch( depth - ((_flags & SegSpinBottom) ? 1 : 0) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::max( topPPitch, bottomPPitch );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
DbU::Unit AutoSegment::getSlack () const
|
|
|
|
{
|
|
|
|
DbU::Unit constraintMin;
|
|
|
|
DbU::Unit constraintMax;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
getConstraints( constraintMin, constraintMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return constraintMax - constraintMin;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DbU::Unit AutoSegment::getCost ( DbU::Unit axis ) const
|
|
|
|
{
|
|
|
|
DbU::Unit optimal = getOptimalMin();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (axis < optimal) return optimal - axis;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
optimal = getOptimalMax();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (axis > optimal) return axis - optimal;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegment* AutoSegment::getCanonical ( DbU::Unit& min, DbU::Unit& max )
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(89) << "AutoSegment::getCanonical() - " << this << endl;
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
min = getSourcePosition ();
|
|
|
|
max = getTargetPosition ();
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (max < min) swap( min, max );
|
|
|
|
|
|
|
|
//ltrace(89) << "[" << DbU::getValueString(min) << " " << DbU::getValueString(max) << "]" << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
AutoSegment* canonical = this;
|
|
|
|
size_t canonicals = isCanonical();
|
|
|
|
size_t aligneds = 1;
|
|
|
|
DbU::Unit collapsedMin;
|
|
|
|
DbU::Unit collapsedMax;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach( AutoSegment*, isegment, getAligneds() ) {
|
|
|
|
if (isegment->isCanonical()) {
|
|
|
|
canonical = *isegment;
|
|
|
|
canonicals++;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
collapsedMin = isegment->getSourcePosition();
|
|
|
|
collapsedMax = isegment->getTargetPosition();
|
|
|
|
if (collapsedMax < collapsedMin) swap( collapsedMin, collapsedMax );
|
|
|
|
if (collapsedMin < min) min = collapsedMin;
|
|
|
|
if (collapsedMax > max) max = collapsedMax;
|
|
|
|
|
|
|
|
aligneds++;
|
|
|
|
}
|
|
|
|
//ltrace(89) << "[" << DbU::getValueString(min) << " " << DbU::getValueString(max) << "]" << endl;
|
|
|
|
ltrace(89) << "Canonical: " << canonical << endl;
|
|
|
|
|
|
|
|
if ( (canonicals > 1) or ( not canonicals and (aligneds > 2) ) ) {
|
|
|
|
cerr << Bug("AutoSegment::getCanonical(): %p:%s"
|
|
|
|
"\n Bad canonization: %d canonicals out of %d collapseds."
|
|
|
|
, base(), _getString().c_str(), canonicals, aligneds ) << endl;
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
cerr << " " << count++ << ": " << this << endl;
|
|
|
|
forEach( AutoSegment*, isegment, getAligneds() )
|
|
|
|
cerr << " " << count++ << ": " << *isegment << endl;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return canonical;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments AutoSegment::getOnSourceContact ( unsigned int direction )
|
|
|
|
{
|
|
|
|
return AutoSegments_OnContact
|
2013-12-03 18:58:58 -06:00
|
|
|
( this, getSource() ).getSubSet( AutoSegments_InDirection(direction) );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegments AutoSegment::getOnTargetContact ( unsigned int direction )
|
|
|
|
{
|
|
|
|
return AutoSegments_OnContact
|
2013-12-03 18:58:58 -06:00
|
|
|
( this, getTarget() ).getSubSet( AutoSegments_InDirection(direction) );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegments AutoSegment::getCachedOnSourceContact ( unsigned int direction )
|
|
|
|
{ return AutoSegments_CachedOnContact( getAutoSource(), direction ); }
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegments AutoSegment::getCachedOnTargetContact ( unsigned int direction )
|
|
|
|
{ return AutoSegments_CachedOnContact( getAutoTarget(), direction ); }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
AutoSegments AutoSegment::getAligneds ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(89) << "AutoSegment::getAligneds() - flags:" << flags << endl;
|
|
|
|
return AutoSegments_Aligneds( this, flags );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegments AutoSegment::getPerpandiculars ()
|
|
|
|
{ return AutoSegments_Perpandiculars( this ); }
|
|
|
|
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
bool AutoSegment::checkDepthSpin () const
|
|
|
|
{
|
|
|
|
bool valid = true;
|
|
|
|
const Layer* sourceLayer = getAutoSource()->getLayer();
|
|
|
|
const Layer* targetLayer = getAutoTarget()->getLayer();
|
|
|
|
|
|
|
|
if ( (_flags & SegSourceTop) and (sourceLayer->getBottom() != getLayer()) ) {
|
|
|
|
cerr << Error("%s\n"
|
|
|
|
" Source is not going above, connected to *top* of %s."
|
|
|
|
, getString(this).c_str()
|
|
|
|
, getString(getAutoSource()).c_str()
|
|
|
|
) << endl;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
if ( (_flags & SegSourceBottom) and (sourceLayer->getTop() != getLayer()) ) {
|
|
|
|
cerr << Error("%s\n"
|
|
|
|
" Source is not going below, connected to *bottom* of %s."
|
|
|
|
, getString(this).c_str()
|
|
|
|
, getString(getAutoSource()).c_str()
|
|
|
|
) << endl;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
if ( (_flags & SegTargetTop) and (targetLayer->getBottom() != getLayer()) ) {
|
|
|
|
cerr << Error("%s\n"
|
|
|
|
" Target is not going above connected to *top* of %s."
|
|
|
|
, getString(this).c_str()
|
|
|
|
, getString(getAutoTarget()).c_str()
|
|
|
|
) << endl;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
if ( (_flags & SegTargetBottom) and (targetLayer->getTop() != getLayer()) ) {
|
|
|
|
cerr << Error("%s\n"
|
|
|
|
" Target is not going below, connected to *bottom* of %s."
|
|
|
|
, getString(this).c_str()
|
|
|
|
, getString(getAutoTarget()).c_str()
|
|
|
|
) << endl;
|
|
|
|
valid = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::setFlagsOnAligneds ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
setFlags( flags );
|
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach( AutoSegment*, isegment, getAligneds() )
|
|
|
|
isegment->setFlags( flags );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::sourceDetach ()
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoContact* source = getAutoSource();
|
|
|
|
if (source) {
|
|
|
|
base()->getSourceHook()->detach();
|
|
|
|
source->cacheDetach( this );
|
|
|
|
unsetFlags( SegNotSourceAligned );
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
setFlags( SegInvalidatedSource );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::targetDetach ()
|
|
|
|
{
|
|
|
|
AutoContact* target = getAutoTarget();
|
|
|
|
if (target) {
|
|
|
|
base()->getTargetHook()->detach();
|
|
|
|
target->cacheDetach( this );
|
|
|
|
unsetFlags( SegNotTargetAligned );
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
setFlags( SegInvalidatedTarget );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::sourceAttach ( AutoContact* source )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (source) {
|
|
|
|
if (not base()->getSourceHook()->isAttached())
|
|
|
|
base()->getSourceHook()->attach( source->base()->getBodyHook() );
|
|
|
|
source->cacheAttach( this );
|
|
|
|
|
|
|
|
// if (source->isHTee() and isHorizontal()) return;
|
|
|
|
// else if (source->isVTee() and isVertical ()) return;
|
|
|
|
// setFlags( SegNotSourceAligned );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::targetAttach ( AutoContact* target )
|
|
|
|
{
|
|
|
|
if (target) {
|
|
|
|
if (not base()->getTargetHook()->isAttached())
|
|
|
|
base()->getTargetHook()->attach( target->base()->getBodyHook() );
|
|
|
|
target->cacheAttach( this );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
// if (target->isHTee() and isHorizontal()) return;
|
|
|
|
// else if (target->isVTee() and isVertical ()) return;
|
|
|
|
// setFlags( SegNotTargetAligned );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
void AutoSegment::mergeUserConstraints ( const Interval& constraints )
|
|
|
|
{
|
|
|
|
ltrace(200) << "mergeUserConstraints() " << this << endl;
|
|
|
|
ltrace(200) << "| " << constraints << " merged with " << _userConstraints << endl;
|
|
|
|
_userConstraints.intersection(constraints);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-20 08:54:34 -06:00
|
|
|
bool AutoSegment::toConstraintAxis ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "toConstraintAxis() " << this << endl;
|
|
|
|
ltracein(200);
|
|
|
|
|
|
|
|
if (not isCanonical()) { ltraceout(200); return false; }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
DbU::Unit constraintMin;
|
|
|
|
DbU::Unit constraintMax;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
getConstraints( constraintMin, constraintMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-05-11 06:04:23 -05:00
|
|
|
// Empty constraint interval: ignore.
|
2013-12-03 18:58:58 -06:00
|
|
|
if (constraintMin > constraintMax) { ltraceout(200); return false; }
|
2010-05-11 06:04:23 -05:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isDogleg()) {
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
DbU::Unit halfSideLength = getAutoSource()->getGCell()->getSide
|
|
|
|
( isHorizontal() ? KbVertical : KbHorizontal ).getHalfSize();
|
|
|
|
constraintMin -= halfSideLength;
|
|
|
|
constraintMax += halfSideLength;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAxis() < constraintMin) {
|
2013-12-20 08:54:34 -06:00
|
|
|
setAxis( constraintMin, flags );
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAxis() > constraintMax) {
|
2013-12-20 08:54:34 -06:00
|
|
|
setAxis( constraintMax, flags );
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-20 08:54:34 -06:00
|
|
|
bool AutoSegment::toOptimalAxis ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "toOptimalAxis() " << this << endl;
|
|
|
|
ltracein(200);
|
|
|
|
|
|
|
|
if (not isCanonical()) { ltraceout(200); return false; }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
DbU::Unit constraintMin;
|
|
|
|
DbU::Unit constraintMax;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
getConstraints( constraintMin, constraintMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
DbU::Unit optimalMin = max( min(getOptimalMin(),constraintMax), constraintMin );
|
|
|
|
DbU::Unit optimalMax = min( max(getOptimalMax(),constraintMin), constraintMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAxis() < optimalMin) {
|
2013-12-20 08:54:34 -06:00
|
|
|
setAxis( optimalMin, flags );
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAxis() > optimalMax) {
|
2013-12-20 08:54:34 -06:00
|
|
|
setAxis( optimalMax, flags );
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-20 08:54:34 -06:00
|
|
|
if (flags & KbRealignate) setAxis( getAxis(), flags );
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::setAxis ( DbU::Unit axis, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isCanonical()) return;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( (axis == getAxis()) and not (flags & KbRealignate) ) return;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ltrace(200) << "setAxis() @"
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
<< ((isHorizontal())?"Y ":"X ") << DbU::toLambda(getAxis())
|
|
|
|
<< " to " << DbU::toLambda(axis) << " on " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
ltracein(80);
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_setAxis( axis );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach( AutoSegment*, isegment, getAligneds() ) {
|
|
|
|
isegment->_setAxis( getAxis() );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ltrace(200) << "No need to process parallels." << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(80);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::computeTerminal ()
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoContact* source = getAutoSource();
|
|
|
|
AutoContact* target = getAutoTarget();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(99) << "computeTerminal() S:" << source->isTerminal()
|
|
|
|
<< " T:" << target->isTerminal()
|
|
|
|
<< " " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (source->isTerminal() or target->isTerminal()) {
|
|
|
|
unsetFlags( SegWeakTerminal );
|
|
|
|
setFlags ( SegStrongTerminal );
|
|
|
|
} else {
|
|
|
|
unsigned int terminalFlag = 0;
|
|
|
|
switch ( _getFlags() & SegWeakTerminal ) {
|
|
|
|
case 0: break;
|
|
|
|
case SegStrongTerminal: terminalFlag = SegWeakTerminal1; break;
|
|
|
|
case SegWeakTerminal1: terminalFlag = SegWeakTerminal1; break;
|
|
|
|
case SegWeakTerminal2: terminalFlag = SegWeakTerminal2; break;
|
|
|
|
default:
|
|
|
|
cerr << Warning("%s has multiple terminal flag sets: %x."
|
|
|
|
,getString(this).c_str()
|
|
|
|
,_flags
|
|
|
|
) << endl;
|
|
|
|
terminalFlag = SegWeakTerminal2; break;
|
|
|
|
}
|
|
|
|
unsetFlags( SegWeakTerminal );
|
|
|
|
setFlags ( terminalFlag );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AutoSegment::computeOptimal ( set<AutoSegment*>& processeds )
|
|
|
|
{
|
|
|
|
ltrace(89) << "computeOptimal() - " << this << endl;
|
|
|
|
ltracein(89);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
DbU::Unit minGCell = getOrigin();
|
|
|
|
DbU::Unit maxGCell = getExtremity();
|
|
|
|
DbU::Unit terminalMin;
|
|
|
|
DbU::Unit terminalMax;
|
|
|
|
AttractorsMap attractors;
|
|
|
|
|
|
|
|
AutoContact* anchor = getAutoSource();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (anchor->isTerminal()) {
|
2010-03-09 09:24:29 -06:00
|
|
|
Box constraintBox = anchor->getConstraintBox();
|
|
|
|
if ( isHorizontal() ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
terminalMin = constraintBox.getYMin();
|
|
|
|
terminalMax = constraintBox.getYMax();
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
terminalMin = constraintBox.getXMin();
|
|
|
|
terminalMax = constraintBox.getXMax();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
attractors.addAttractor( terminalMin );
|
|
|
|
if (terminalMin != terminalMax)
|
|
|
|
attractors.addAttractor( terminalMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
anchor = getAutoTarget();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (anchor->isTerminal()) {
|
2010-03-09 09:24:29 -06:00
|
|
|
Box constraintBox = anchor->getConstraintBox();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isHorizontal()) {
|
|
|
|
terminalMin = constraintBox.getYMin();
|
|
|
|
terminalMax = constraintBox.getYMax();
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
terminalMin = constraintBox.getXMin();
|
|
|
|
terminalMax = constraintBox.getXMax();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
attractors.addAttractor( terminalMin );
|
|
|
|
if (terminalMin != terminalMax)
|
|
|
|
attractors.addAttractor( terminalMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
forEach( AutoSegment*, autoSegment, getPerpandiculars() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
ltrace(89) << "Perpandicular " << *autoSegment << endl;
|
|
|
|
ltracein(89);
|
2013-12-03 18:58:58 -06:00
|
|
|
if (autoSegment->isLocal()) {
|
|
|
|
if (not autoSegment->isStrongTerminal()) { ltraceout(89); continue; }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
DbU::Unit terminalMin;
|
|
|
|
DbU::Unit terminalMax;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getTerminalInterval( *autoSegment
|
|
|
|
, NULL
|
|
|
|
, isHorizontal()
|
|
|
|
, terminalMin
|
|
|
|
, terminalMax )) {
|
|
|
|
attractors.addAttractor( terminalMin );
|
|
|
|
if (terminalMin != terminalMax)
|
|
|
|
attractors.addAttractor( terminalMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bool isMin = true;
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isHorizontal()
|
|
|
|
and (autoSegment->getAutoSource()->getGCell()->getRow() == _gcell->getRow()) )
|
2010-03-09 09:24:29 -06:00
|
|
|
isMin = false;
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isVertical()
|
|
|
|
and (autoSegment->getAutoSource()->getGCell()->getColumn() == _gcell->getColumn()) )
|
2010-03-09 09:24:29 -06:00
|
|
|
isMin = false;
|
2013-12-03 18:58:58 -06:00
|
|
|
attractors.addAttractor( (isMin) ? minGCell : maxGCell );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
ltraceout(89);
|
|
|
|
}
|
|
|
|
|
|
|
|
DbU::Unit optimalMin;
|
|
|
|
DbU::Unit optimalMax;
|
|
|
|
DbU::Unit constraintMin;
|
|
|
|
DbU::Unit constraintMax;
|
2013-12-03 18:58:58 -06:00
|
|
|
getConstraints( constraintMin, constraintMax );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (attractors.getAttractorsCount()) {
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
ltrace(89) << "Lower Median " << DbU::toLambda(attractors.getLowerMedian()) << endl;
|
|
|
|
ltrace(89) << "Upper Median " << DbU::toLambda(attractors.getUpperMedian()) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
optimalMin = attractors.getLowerMedian();
|
|
|
|
optimalMax = attractors.getUpperMedian();
|
|
|
|
} else {
|
|
|
|
optimalMin = 0;
|
2013-12-03 18:58:58 -06:00
|
|
|
optimalMax = (isHorizontal()) ? _gcell->getBoundingBox().getYMax()
|
|
|
|
: _gcell->getBoundingBox().getXMax();
|
|
|
|
}
|
|
|
|
|
|
|
|
setInBound( constraintMin, constraintMax, optimalMin );
|
|
|
|
setInBound( constraintMin, constraintMax, optimalMax );
|
|
|
|
|
|
|
|
ltrace(89) << "Applying constraint on: " << this << endl;
|
|
|
|
setOptimalMin( optimalMin );
|
|
|
|
setOptimalMax( optimalMax );
|
|
|
|
processeds.insert( this );
|
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, autoSegment, getAligneds() ) {
|
|
|
|
ltrace(89) << "Applying constraint on: " << *autoSegment << endl;
|
|
|
|
autoSegment->setOptimalMin( optimalMin );
|
|
|
|
autoSegment->setOptimalMax( optimalMax );
|
|
|
|
processeds.insert( (*autoSegment) );
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(89);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegment* AutoSegment::canonize ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
ltrace(159) << "canonize() - " << this << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
// if (isCanonical() and isGlobal()) {
|
|
|
|
// ltrace(159) << "* " << this << " canonical" << endl;
|
|
|
|
// return this;
|
|
|
|
// }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
vector<AutoSegment*> segments;
|
|
|
|
AutoSegment* canonical = this;
|
|
|
|
bool hasCanonical = isCanonical();
|
|
|
|
bool hasGlobal = isGlobal();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach( AutoSegment*, isegment, getAligneds(flags) ) {
|
|
|
|
if (isegment->isFixed()) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
hasGlobal = hasGlobal or isegment->isGlobal();
|
|
|
|
segments.push_back( *isegment );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not hasCanonical) {
|
|
|
|
if (isegment->isCanonical()) {
|
|
|
|
ltrace(159) << "* " << *isegment << " canonical already set" << endl;
|
|
|
|
canonical = *isegment;
|
|
|
|
hasCanonical = true;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (CompareId()(*isegment,canonical)) canonical = *isegment;
|
|
|
|
}
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
canonical->setFlags( SegCanonical );
|
|
|
|
if (hasGlobal) {
|
|
|
|
for ( size_t i=0 ; i<segments.size() ; ++i )
|
|
|
|
segments[i]->setFlags( SegWeakGlobal );
|
|
|
|
} else {
|
|
|
|
for ( size_t i=0 ; i<segments.size() ; ++i )
|
|
|
|
segments[i]->unsetFlags( SegWeakGlobal );
|
|
|
|
}
|
|
|
|
if (segments.empty()) setFlags( SegNotAligned );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isCanonical()) { ltrace(159) << "* " << this << " canonical" << endl; }
|
|
|
|
else {
|
|
|
|
ltrace(159) << "* " << this << " not canonical" << endl;
|
|
|
|
ltrace(159) << "* " << canonical << " *is* the canonical" << endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
setFlags ( SegCanonical );
|
|
|
|
unsetFlags( SegWeakGlobal );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return canonical;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
size_t AutoSegment::getAlignedContacts ( map<AutoContact*,int>& innerContacts ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
map<AutoContact*,int>::iterator icontact;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
innerContacts.clear();
|
|
|
|
innerContacts.insert( make_pair(getAutoSource(),0x1) );
|
|
|
|
innerContacts.insert( make_pair(getAutoTarget(),0x4) );
|
|
|
|
|
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) {
|
|
|
|
if ( (icontact = innerContacts.find(isegment->getAutoSource())) != innerContacts.end() ) {
|
|
|
|
if (icontact->second & 0x1) icontact->second |= 0x2;
|
|
|
|
else icontact->second |= 0x1;
|
|
|
|
} else
|
|
|
|
innerContacts.insert( make_pair(getAutoSource(),0x1) );
|
|
|
|
|
|
|
|
if ( (icontact = innerContacts.find(isegment->getAutoTarget())) != innerContacts.end() ) {
|
|
|
|
if (icontact->second & 0x4) icontact->second |= 0x8;
|
|
|
|
else icontact->second |= 0x4;
|
|
|
|
} else
|
|
|
|
innerContacts.insert( make_pair(getAutoTarget(),0x4) );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return innerContacts.size();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
Interval AutoSegment::getMinSpanU () const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
map<AutoContact*,int> contacts;
|
|
|
|
map<AutoContact*,int>::iterator icontact;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
getAlignedContacts( contacts );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
DbU::Unit spanMin = DbU::Min;
|
|
|
|
DbU::Unit spanMax = DbU::Max;
|
|
|
|
Interval constraints;
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int direction = getDirection();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
for ( icontact=contacts.begin() ; icontact != contacts.end() ; icontact++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
constraints = icontact->first->getUConstraints( direction );
|
|
|
|
if (icontact->second == 0x1) {
|
|
|
|
spanMin = max( spanMin, constraints.getVMax() );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
if (icontact->second == 0x4) {
|
|
|
|
spanMax = min( spanMax, constraints.getVMin() );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Interval(spanMin,spanMax);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
size_t AutoSegment::getPerpandicularsBound ( set<AutoSegment*>& bounds )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
map<AutoContact*,int> contacts;
|
2010-03-09 09:24:29 -06:00
|
|
|
map<AutoContact*,int>::iterator icontact;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
getAlignedContacts( contacts );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
for ( icontact=contacts.begin() ; icontact != contacts.end() ; icontact++ ) {
|
|
|
|
if ( (icontact->second == 0x1) or (icontact->second == 0x4) ) {
|
|
|
|
forEach ( Segment*, isegment, icontact->first->getSlaveComponents().getSubSet<Segment*>() ) {
|
|
|
|
AutoSegment* autoSegment = Session::lookup ( *isegment );
|
|
|
|
if (not autoSegment) continue;
|
|
|
|
if (autoSegment->getDirection() == getDirection()) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bounds.insert( autoSegment );
|
|
|
|
}
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return bounds.size();
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::changeDepth ( unsigned int depth, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "changeDepth() " << depth << " - " << this << endl;
|
|
|
|
ltracein(200);
|
|
|
|
Session::invalidate( getNet() );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
_changeDepth( depth, flags & ~KbPropagate );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, getAligneds(KbNoCheckLayer) ) {
|
|
|
|
(*isegment)->_changeDepth( depth, flags & ~KbPropagate );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltraceout(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
void AutoSegment::_changeDepth ( unsigned int depth, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
ltrace(200) << "_changeDepth() - " << this << endl;
|
|
|
|
ltracein(200);
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
invalidate( KbNoFlags );
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
setFlags( SegInvalidatedLayer|SegInvalidatedSource|SegInvalidatedTarget );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth);
|
|
|
|
if (getLayer() != newLayer) {
|
|
|
|
setLayer( newLayer );
|
|
|
|
|
|
|
|
getAutoSource()->invalidate( KbTopology|KbNoCheckLayer );
|
|
|
|
getAutoTarget()->invalidate( KbTopology|KbNoCheckLayer );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not (flags & KbWithNeighbors)) {
|
2010-03-09 09:24:29 -06:00
|
|
|
ltraceout(200);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
forEach ( AutoSegment*, isegment, getCachedOnSourceContact(KbDirectionMask) ) {
|
|
|
|
if ((*isegment) == this) continue;
|
|
|
|
if ((*isegment)->isGlobal ()) continue;
|
|
|
|
if ((*isegment)->isTerminal()) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not ((*isegment)->isHorizontal() xor isHorizontal()))
|
|
|
|
(*isegment)->_changeDepth( depth , KbNoFlags );
|
|
|
|
else
|
|
|
|
(*isegment)->_changeDepth( depth-1, KbNoFlags );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
forEach ( AutoSegment*, isegment, getCachedOnTargetContact(KbDirectionMask) ) {
|
|
|
|
if ((*isegment) == this) continue;
|
|
|
|
if ((*isegment)->isGlobal ()) continue;
|
|
|
|
if ((*isegment)->isTerminal()) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not ((*isegment)->isHorizontal() xor isHorizontal()))
|
|
|
|
(*isegment)->_changeDepth( depth , KbNoFlags );
|
|
|
|
else
|
|
|
|
(*isegment)->_changeDepth( depth-1, KbNoFlags );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
2013-12-03 18:58:58 -06:00
|
|
|
getGCells( gcells );
|
|
|
|
for ( size_t i=0 ; i<gcells.size() ; ++i )
|
|
|
|
gcells[i]->invalidate();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ltraceout(200);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::canSlacken ( unsigned int flags ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
ltrace(200) << "AutoSegment::canSlacken()" << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isGlobal() and not (flags & KbPropagate)) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (_canSlacken()) return true;
|
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) {
|
|
|
|
if (isegment->_canSlacken()) return true;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::slacken ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
bool success = false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
success = success or _slacken( flags );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, getAligneds() ) {
|
|
|
|
success = success or (*isegment)->_slacken( flags );
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return success;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-25 11:16:27 -06:00
|
|
|
float AutoSegment::getMaxUnderDensity ( unsigned int flags )
|
|
|
|
{
|
|
|
|
ltrace(200) << "AutoSegment::getMaxUnderDensity() " << endl;
|
|
|
|
|
|
|
|
GCell* begin = NULL;
|
|
|
|
GCell* end = NULL;
|
|
|
|
|
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(getLayer());
|
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
2013-12-03 18:58:58 -06:00
|
|
|
getGCells( gcells );
|
2011-01-25 11:16:27 -06:00
|
|
|
begin = *gcells.begin ();
|
|
|
|
end = *gcells.rbegin();
|
|
|
|
|
|
|
|
float maxDensity = 0.0;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
|
|
|
|
maxDensity = std::max( maxDensity, gcells[i]->getFeedthroughs(depth) );
|
2011-01-25 11:16:27 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, getAligneds() ) {
|
|
|
|
isegment->getGCells( gcells );
|
|
|
|
if ((*gcells.begin ())->getIndex() < begin->getIndex()) begin = *gcells.begin ();
|
|
|
|
if ((*gcells.rbegin())->getIndex() > end ->getIndex()) end = *gcells.rbegin();
|
2011-01-25 11:16:27 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
|
|
|
|
maxDensity = std::max( maxDensity, gcells[i]->getFeedthroughs(depth) );
|
2011-01-25 11:16:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return maxDensity;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::canPivotUp ( float reserve, unsigned int flags ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "AutoSegment::canPivotUp() - " << flags
|
|
|
|
<< " (reserve:" << reserve << ")" << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isLayerChange() or isFixed() ) return false;
|
|
|
|
if ( isStrongTerminal() or isLocal() ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
|
|
|
|
if (depth+2 >= Session::getRoutingGauge()->getDepth()) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
2013-12-03 18:58:58 -06:00
|
|
|
getGCells( gcells );
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth+2,reserve)) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( not (flags&KbIgnoreContacts) ) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
ltrace(200) << getAutoSource() << endl;
|
|
|
|
ltrace(200) << getAutoTarget() << endl;
|
|
|
|
ltrace(200) << "min depths, Segment:" << depth
|
|
|
|
<< " S:" << getAutoSource()->getMinDepth()
|
|
|
|
<< " T:" << getAutoTarget()->getMinDepth() << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAutoSource()->getMinDepth() < depth) return false;
|
|
|
|
if (getAutoTarget()->getMinDepth() < depth) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds(flags) ) {
|
|
|
|
isegment->getGCells( gcells );
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth+2,reserve)) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isegment->getAutoSource()->getMinDepth() < depth) return false;
|
|
|
|
if (isegment->getAutoTarget()->getMinDepth() < depth) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ltrace(200) << "AutoSegment::canPivotUp() - true [no propagate]" << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ltrace(200) << "AutoSegment::canPivotUp() - true [propagate]" << endl;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::canPivotDown ( float reserve, unsigned int flags ) const
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
{
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "AutoSegment::canPivotDown()"
|
|
|
|
<< " (reserve:" << reserve << ")" << endl;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isLayerChange() or isFixed() ) return false;
|
|
|
|
if ( isStrongTerminal() or isLocal() ) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
|
|
|
|
if (depth < 3) return false;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
2013-12-03 18:58:58 -06:00
|
|
|
getGCells( gcells );
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth-2,reserve)) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
ltrace(200) << getAutoSource() << endl;
|
|
|
|
ltrace(200) << getAutoTarget() << endl;
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
ltrace(200) << "max depths, Segment:" << depth
|
|
|
|
<< " S:" << getAutoSource()->getMaxDepth()
|
|
|
|
<< " T:" << getAutoTarget()->getMaxDepth() << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getAutoSource()->getMaxDepth() > depth) return false;
|
|
|
|
if (getAutoTarget()->getMaxDepth() > depth) return false;
|
|
|
|
if (not (flags & KbPropagate)) {
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
ltrace(200) << "AutoSegment::canPivotDown() - true [no propagate]" << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds() ) {
|
|
|
|
isegment->getGCells( gcells );
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth-2,reserve)) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isegment->getAutoSource()->getMaxDepth() < depth) return false;
|
|
|
|
if (isegment->getAutoTarget()->getMaxDepth() < depth) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "AutoSegment::canPivotDown() - true [propagate]" << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::canMoveUp ( float reserve, unsigned int flags ) const
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "AutoSegment::canMoveUp() " << flags
|
|
|
|
<< " (reserve:" << reserve << ")" << endl;
|
|
|
|
|
|
|
|
GCell* begin = NULL;
|
|
|
|
GCell* end = NULL;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
if ( isLayerChange() or isFixed() ) return false;
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isStrongTerminal() and (not (flags & KbAllowTerminal)) ) return false;
|
|
|
|
if ( isLocal() and (not (flags & KbAllowLocal )) ) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
size_t depth = Session::getRoutingGauge()->getLayerDepth(getLayer()) + 2;
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
if (depth > Session::getConfiguration()->getAllowedDepth()) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
2013-12-03 18:58:58 -06:00
|
|
|
getGCells( gcells );
|
2011-01-09 12:08:31 -06:00
|
|
|
begin = *gcells.begin ();
|
|
|
|
end = *gcells.rbegin();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth,reserve)) {
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
ltrace(200) << "Not enough free track in " << gcells[i] << endl;
|
|
|
|
return false;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
ltrace(200) << "Enough free track under canonical segment." << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( isLocal() and not (flags & KbPropagate) ) {
|
|
|
|
if (not getAutoSource()->canMoveUp(this)) return false;
|
|
|
|
if (not getAutoTarget()->canMoveUp(this)) return false;
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-03-15 04:47:37 -05:00
|
|
|
//bool hasGlobalSegment = false;
|
2013-12-03 18:58:58 -06:00
|
|
|
if ((flags & KbPropagate) and not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, const_cast<AutoSegment*>(this)->getAligneds(flags) ) {
|
|
|
|
if (isegment->isFixed ()) return false;
|
2014-03-15 04:47:37 -05:00
|
|
|
//if (isegment->isGlobal()) hasGlobalSegment = true;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
isegment->getGCells( gcells );
|
2011-01-09 12:08:31 -06:00
|
|
|
if ( (*gcells.begin ())->getIndex() < begin->getIndex() ) begin = *gcells.begin ();
|
|
|
|
if ( (*gcells.rbegin())->getIndex() > end ->getIndex() ) end = *gcells.rbegin();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not gcells[i]->hasFreeTrack(depth,reserve)) {
|
2010-03-09 09:24:29 -06:00
|
|
|
ltrace(200) << "Not enough free track in " << gcells[i] << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( (depth >= 4) and (flags & KbWithPerpands) ) {
|
|
|
|
float fragmentation = begin->getFragmentation( depth-1 );
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "Check begin GCell perpandicular fragmentation: " << fragmentation << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (fragmentation < 0.5) {
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "Not enough free track for perpandicular in begin GCell "
|
|
|
|
<< "(frag:" << fragmentation << ")."
|
|
|
|
<< endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
fragmentation = end->getFragmentation( depth-1 );
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "Check end GCell perpandicular fragmentation: " << fragmentation << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (fragmentation < 0.5) {
|
2011-01-09 12:08:31 -06:00
|
|
|
ltrace(200) << "Not enough free track for perpandicular in end GCell "
|
|
|
|
<< "(frag:" << fragmentation << ")."
|
|
|
|
<< endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./katabatic:
- New: ChipTools, regroup all datas and utilities to manage a full-chip
design.
- Change: In LoadGrByNet/GCellConfiguration::_GCell_xG_1Pad(), uses straight
perpandicular wires on top & right pads. The GCells under those connectors
are fully saturated, wires must go out as straight as possible.
- Change: In AutoHorizontal/AutoVertical, update the "terminal" flag after
slackening. This is to avoid global that are no longer connected to
terminals behave as such.
- Change: In AutoSegment::canMoveUp() & canPivotUp(), prevent all local segments
to go up. This is to avoid cluttering upper levels with small segments.
- Change: In GCellConfiguration, for xG_xL3, detect straight vertical topologies
and for them to be fixed (new flag FIXED_GLOBAL set by the topological
builder instead of the constructor). This prevent the router to do
stupid things...
To sets the "Fixed" flag *after* the axis of global segments have been
positionned correctly adds a "_toFixGlobals" static table lookup.
- Change: In GCell::stepDesaturate(), if less than one free track remains in
the upper layer, do not move up the segment. This allows from a minimum
free room for expansion.
- Change: In GCell::_getString(), display indexes and layer names in various
saturation tables.
- Change: In AutoSegment, allow move up of local Segment. ::moveUp() and
::canMoveUp() arguments go from booleans to flags, which are more
explicits.
2010-12-04 09:25:18 -06:00
|
|
|
bool AutoSegment::moveUp ( unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2011-01-25 11:16:27 -06:00
|
|
|
//if ( not canMoveUp(0.0,flags) ) return false;
|
2013-12-03 18:58:58 -06:00
|
|
|
changeDepth( Session::getRoutingGauge()->getLayerDepth(getLayer()) + 2, flags&KbPropagate );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
bool AutoSegment::moveDown ( unsigned int flags )
|
|
|
|
{
|
2011-01-25 11:16:27 -06:00
|
|
|
//if ( not canPivotDown(0.0,flags) ) return false;
|
2013-12-03 18:58:58 -06:00
|
|
|
changeDepth( Session::getRoutingGauge()->getLayerDepth(getLayer()) - 2, flags&KbPropagate );
|
* ./katabatic:
- New: In AutoSegment, adds a "_parent" attribute to keep track of the fragmentation
processus. Currently used only for strap segments, points to the original
segment in the appropriate direction (before the split).
- New: In GCell & LayerAssign, new method of layer assignment. Move up
the whole net trunk if only one of it's segment is inside an over-saturated
GCell. AutoSegment are moved up only if there is at least 2 free tracks
remaining on the upper level.
- Change: In Session::_canonize(), uses the lowest segment Id as canonical.
More reliable than geometricals criterions in the end. Assuming that the
segments are being created in deterministic order, which *should* be the
case consediring the way we are walking through the global routing.
- Change: In AutoSegment, completly suppress the CompareCanonical(), replace
it by the much simpler CompareId().
- Change: In GCell::rpDesaturate(), stops desaturation when bottom density
is under 0.5, otherwise we are causing a severe imbalance in M2/M4
densities. All wires pushed up to M4...
- Change: In ChipTools, for the Pad's RoutingPad, reslect the best component
using the one in the lowest layer. To avoid problem when splitting
AutoContact as we expect the base Contact to be on the lower layer.
- Bug: In GCellConfiguration::_GCell_xG_xL1_xL3(), add H/V alignement constraints
in fork case. This allow NE/SW contact to be splitted correctly later.
- Bug: In AutoContact::split(), the connexity on the splitted contacts was
not correctly restored, leading to canonization and parentage looping
errors. This was concealed by the Kite Track::_check() bug (incomplete
individual TrackSegment checking).
2010-12-30 12:41:19 -06:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
#if THIS_IS_DISABLED
|
|
|
|
|
|
|
|
|
2010-12-12 15:43:25 -06:00
|
|
|
bool AutoSegment::shearUp ( GCell* upGCell, AutoSegment*& movedUp, float reserve, unsigned int flags )
|
|
|
|
{
|
|
|
|
ltrace(200) << "AutoSegment::shearUp() " << this << endl;
|
|
|
|
|
|
|
|
movedUp = NULL;
|
|
|
|
|
|
|
|
if ( isLayerChange() or isFixed() /*or isTerminal()*/ or isLocal() ) return false;
|
|
|
|
|
|
|
|
size_t upDepth = Session::getRoutingGauge()->getLayerDepth(getLayer()) + 2;
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
if ( upDepth > Session::getConfiguration()->getAllowedDepth() ) return false;
|
2010-12-12 15:43:25 -06:00
|
|
|
|
|
|
|
vector<GCell*> gcells;
|
|
|
|
getGCells ( gcells );
|
|
|
|
|
|
|
|
size_t iupGCell = 0;
|
|
|
|
for ( ; iupGCell<gcells.size() ; ++iupGCell ) {
|
|
|
|
if ( gcells[iupGCell] == upGCell ) break;
|
|
|
|
}
|
|
|
|
if ( iupGCell == gcells.size() ) {
|
|
|
|
cerr << Warning("Shear start %s not under %s."
|
|
|
|
,getString(upGCell).c_str()
|
|
|
|
,getString(this).c_str()
|
|
|
|
) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
GCell* rightShear = NULL;
|
|
|
|
for ( size_t i=iupGCell ; i<gcells.size() ; i++ ) {
|
|
|
|
if ( not gcells[i]->hasFreeTrack(upDepth,reserve) ) {
|
|
|
|
ltrace(200) << "Right shearing @ " << gcells[i] << endl;
|
|
|
|
rightShear = gcells[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GCell* leftShear = NULL;
|
|
|
|
if ( iupGCell > 0 ) {
|
|
|
|
size_t i = iupGCell;
|
|
|
|
do {
|
|
|
|
--i;
|
|
|
|
if ( not gcells[i]->hasFreeTrack(upDepth,reserve) ) {
|
|
|
|
ltrace(200) << "Left shearing @ " << gcells[i] << endl;
|
|
|
|
leftShear = gcells[i];
|
|
|
|
}
|
|
|
|
} while (i > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoSegment* before = this;
|
2013-12-03 18:58:58 -06:00
|
|
|
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
|
2010-12-12 15:43:25 -06:00
|
|
|
|
|
|
|
if ( leftShear ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
makeDogleg ( leftShear, true );
|
2010-12-12 15:43:25 -06:00
|
|
|
movedUp = doglegs[2];
|
|
|
|
} else {
|
|
|
|
before = NULL;
|
|
|
|
movedUp = this;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( rightShear ) makeDogleg(rightShear,true);
|
2010-12-12 15:43:25 -06:00
|
|
|
|
|
|
|
if ( movedUp->moveUp(flags) ) {
|
|
|
|
if ( rightShear or leftShear )
|
|
|
|
cinfo << "Shearing Up " << this << "." << endl;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
movedUp = NULL;
|
|
|
|
return false;
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
#endif
|
2010-12-12 15:43:25 -06:00
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int AutoSegment::canDogleg ( Interval interval )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "AutoSegment::canDogleg(Interval) " << interval << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
size_t leftDogleg = 0;
|
|
|
|
size_t rightDogleg = 0;
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getSpanU().contains(interval.getVMin())) leftDogleg++;
|
|
|
|
if (getSpanU().contains(interval.getVMax())) rightDogleg++;
|
|
|
|
|
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, getAligneds() ) {
|
|
|
|
if (isegment->getSpanU().contains(interval.getVMin())) {
|
|
|
|
if (isegment->isFixed()) return false;
|
|
|
|
leftDogleg++;
|
|
|
|
}
|
|
|
|
if (isegment->getSpanU().contains(interval.getVMax())) {
|
|
|
|
if (isegment->isFixed()) return 0;
|
|
|
|
rightDogleg++;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( (leftDogleg == 1) and (rightDogleg <= 1) ) return KbDoglegOnLeft;
|
|
|
|
if ( (leftDogleg <= 1) and (rightDogleg == 1) ) return KbDoglegOnRight;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ltrace(200) << "leftCount:" << leftDogleg << " rightCount:" << rightDogleg << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegment* AutoSegment::makeDogleg ( AutoContact* from )
|
|
|
|
{
|
|
|
|
ltrace(200) << "AutoSegment::makeDogleg(AutoContact*) " << from << endl;
|
|
|
|
ltracein(200);
|
|
|
|
ltrace(200) << this << endl;
|
|
|
|
|
|
|
|
RoutingGauge* rg = Session::getRoutingGauge();
|
|
|
|
size_t segmentDepth = rg->getLayerDepth( getLayer() );
|
|
|
|
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
|
|
|
|
size_t index = doglegs.size();
|
|
|
|
bool isSource = (getAutoSource() == from);
|
|
|
|
|
|
|
|
ltrace(200) << "isSource:" << isSource << endl;
|
|
|
|
|
|
|
|
makeDogleg( from->getGCell(), KbNoCheckLayer );
|
|
|
|
if (doglegs.size() == index) {
|
|
|
|
ltraceout(200);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
doglegs[ index+1 ]->setAxis( isHorizontal() ? from->getX() : from->getY() );
|
|
|
|
|
|
|
|
if (not from->getLayer()->contains(getLayer())) {
|
|
|
|
ltrace(200) << "Contact layer do not contains Segment layer, adjust layers" << endl;
|
|
|
|
|
|
|
|
if (getLayer()->above(from->getLayer())) {
|
|
|
|
ltrace(200) << "Go Down from depth " << segmentDepth << endl;
|
|
|
|
|
|
|
|
doglegs[ index + 1 ]->setLayer( rg->getRoutingLayer(segmentDepth-1) );
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
|
|
|
|
|
|
|
if (isSource) {
|
|
|
|
doglegs[ index + 0 ]->setLayer( rg->getRoutingLayer(segmentDepth-2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
|
|
|
ltrace(200) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
|
|
|
} else {
|
|
|
|
doglegs[ index + 2 ]->setLayer( rg->getRoutingLayer(segmentDepth-2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
|
|
|
ltrace(200) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ltrace(200) << "Go Up from depth " << segmentDepth << endl;
|
|
|
|
|
|
|
|
doglegs[ index + 1 ]->setLayer( rg->getRoutingLayer(segmentDepth+1) );
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
|
|
|
|
|
|
|
if (isSource) {
|
|
|
|
doglegs[ index + 0 ]->setLayer( rg->getRoutingLayer(segmentDepth+2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
|
|
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth ) );
|
|
|
|
ltrace(200) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
|
|
|
} else {
|
|
|
|
doglegs[ index + 2 ]->setLayer( rg->getRoutingLayer(segmentDepth+2) );
|
|
|
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
|
|
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth ) );
|
|
|
|
ltrace(200) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
|
|
|
ltrace(200) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(200);
|
|
|
|
return doglegs[ index + (isSource?0:2) ];
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int AutoSegment::makeDogleg ( Interval interval, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(200) << "AutoSegment::makeDogleg(Interval) - " << interval << endl;
|
|
|
|
ltracein(200);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool leftDogleg = true;
|
|
|
|
unsigned int rflags = 0;
|
2010-03-09 09:24:29 -06:00
|
|
|
size_t leftDoglegCount = 0;
|
|
|
|
size_t rightDoglegCount = 0;
|
|
|
|
AutoSegment* leftCandidate = NULL;
|
|
|
|
AutoSegment* rightCandidate = NULL;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (getSpanU().contains(interval.getVMin())) { leftCandidate = this; leftDoglegCount++; }
|
|
|
|
if (getSpanU().contains(interval.getVMax())) { rightCandidate = this; rightDoglegCount++; }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, isegment, getAligneds(flags) ) {
|
|
|
|
if (isegment->getSpanU().contains(interval.getVMin())) { leftCandidate = *isegment; leftDoglegCount++; }
|
|
|
|
if (isegment->getSpanU().contains(interval.getVMax())) { rightCandidate = *isegment; rightDoglegCount++; }
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( (leftDoglegCount != 1) and (rightDoglegCount != 1) ) { ltraceout(200); return 0; }
|
|
|
|
if (not leftDoglegCount) {
|
2010-03-09 09:24:29 -06:00
|
|
|
leftDogleg = false;
|
|
|
|
leftCandidate = rightCandidate;
|
|
|
|
rightCandidate = NULL;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (leftCandidate and rightCandidate) {
|
|
|
|
ltrace(200) << "Left Constraint: " << leftCandidate->getSourceConstraints(KbNativeConstraints) << endl;
|
|
|
|
ltrace(200) << "Right Constraint: " << rightCandidate->getTargetConstraints(KbNativeConstraints) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if ( leftCandidate ->getTargetConstraints(KbNativeConstraints).getSize()
|
|
|
|
< rightCandidate->getSourceConstraints(KbNativeConstraints).getSize() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
leftCandidate = rightCandidate;
|
|
|
|
leftDogleg = false;
|
|
|
|
}
|
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not leftCandidate) {
|
2010-03-09 09:24:29 -06:00
|
|
|
leftCandidate = rightCandidate;
|
|
|
|
leftDogleg = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (leftCandidate) {
|
|
|
|
DbU::Unit axis;
|
|
|
|
// Ugly: Hard-wired track spacing.
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
if (leftDogleg) axis = interval.getVMin() - getPitch();
|
|
|
|
else axis = interval.getVMax() + getPitch();
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
ltrace(200) << "Break @" << DbU::getValueString(axis) << " " << leftCandidate << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int direction = getDirection();
|
|
|
|
GCell* gcell = leftCandidate->getAutoSource()->getGCell();
|
|
|
|
GCell* end = leftCandidate->getAutoTarget()->getGCell();
|
|
|
|
while ( gcell != end ) {
|
|
|
|
if (gcell->getSide(direction).contains(axis)) break;
|
|
|
|
gcell = (direction == KbHorizontal) ? gcell->getRight() : gcell->getUp();
|
|
|
|
}
|
|
|
|
|
|
|
|
ltrace(200) << "In " << gcell << endl;
|
|
|
|
rflags = leftCandidate->_makeDogleg( gcell, flags );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
|
|
|
|
if (doglegs.size() >= 2) {
|
|
|
|
ltrace(200) << "AutoSegment::makeDogleg(): @" << DbU::getValueString(axis) << endl;
|
|
|
|
doglegs[1]->setAxis( axis );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
ltraceout(200);
|
|
|
|
return rflags | (leftDogleg ? KbDoglegOnLeft : KbDoglegOnRight);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int AutoSegment::makeDogleg ( GCell* doglegGCell, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(500) << "Deter| AutoSegment::makeDogleg(GCell*) " << doglegGCell << endl;
|
|
|
|
ltrace(500) << "Deter| in " << this << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
ltracein(160);
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
unsigned int rflags = 0;
|
|
|
|
|
|
|
|
if (doglegGCell->isUnderIoPad()) {
|
|
|
|
cerr << Bug( "Attempt to make a dogleg in a GCell under a Pad\n"
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
" %s\n"
|
2013-12-03 18:58:58 -06:00
|
|
|
" %s"
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
, getString(this).c_str()
|
2013-12-03 18:58:58 -06:00
|
|
|
, getString(doglegGCell).c_str() ) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (isFixed()) {
|
|
|
|
cerr << Error( "AutoSegment::makeDogleg(): Cannot make a dog leg on a fixed segment.\n"
|
|
|
|
" (on: %s)", _getString().c_str() ) << endl;
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (doglegGCell->getSide(getDirection()).intersect(getSpanU())) {
|
2010-03-09 09:24:29 -06:00
|
|
|
ltrace(159) << "Dogleg in " << this << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
rflags = _makeDogleg( doglegGCell, flags );
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
|
|
|
ltrace(159) << "Looking in aligneds." << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not isNotAligned()) {
|
|
|
|
forEach ( AutoSegment*, aligned, getAligneds(flags) ) {
|
|
|
|
ltrace(159) << "| Try in " << *aligned << endl;
|
|
|
|
if (doglegGCell->getSide(getDirection()).intersect(aligned->getSpanU())) {
|
|
|
|
ltrace(159) << "Dogleg in " << *aligned << endl;
|
|
|
|
rflags = aligned->_makeDogleg( doglegGCell, flags );
|
|
|
|
ltraceout(160);
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
cerr << Bug("Cannot make a dogleg in %s at %s"
|
2013-12-03 18:58:58 -06:00
|
|
|
,_getString().c_str(), getString(doglegGCell).c_str()) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
ltraceout(160);
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
return rflags;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool AutoSegment::_check () const
|
|
|
|
{
|
|
|
|
bool coherency = true;
|
|
|
|
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
coherency = checkNotInvalidated() and coherency;
|
|
|
|
coherency = checkPositions() and coherency;
|
|
|
|
coherency = checkConstraints() and coherency;
|
|
|
|
coherency = checkDepthSpin() and coherency;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return coherency;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
string AutoSegment::_getStringFlags () const
|
|
|
|
{
|
|
|
|
string state;
|
|
|
|
state += isFixed () ?" F":" -";
|
|
|
|
state += isUnsetAxis () ? "u": "-";
|
|
|
|
state += isStrap () ? "S": "-";
|
|
|
|
state += isCanonical () ? "C": "-";
|
|
|
|
state += isGlobal () ? "G": "-";
|
|
|
|
state += isWeakGlobal () ? "g": "-";
|
|
|
|
state += isStrongTerminal() ? "T": "-";
|
|
|
|
state += isWeakTerminal1 () ? "W": "-";
|
|
|
|
state += isWeakTerminal2 () ? "w": "-";
|
|
|
|
state += isNotAligned () ? "A": "-";
|
|
|
|
state += isSlackened () ? "S": "-";
|
|
|
|
state += isInvalidated () ? "i": "-";
|
Support of RoutingGauge, part 2.
In Katabatic & Kite, remove all hard-coded values related to track pitches.
* New: In <Session>, add more convenience function to access RoutingGauge
characteristics.
* New: In <AutoSegment>, <AutoContact>, add support for the "depth spin",
that is, if the source/target contacts are going "top" or "down".
Used to compute the perpandicular pitch. Need a small modification
of the revalidation mechanism. The observers of <AutoSegment> are
notified when the spin changes.
* New: In <AutoSegment>, the getPPitch() method allow to compute the
"perpandicular pitch". For now it is simply the greatest from the
source perpandicular pitch and the target perpandicular pitch.
Make uses of the "depth spin".
* New: In <TrackElement>, <TrackSegment>, cache the perpandicular pitch.
Updated through the notification from the observable.
2014-05-19 10:58:38 -05:00
|
|
|
|
|
|
|
if (_flags & SegSourceTop) state += 'T';
|
|
|
|
else if (_flags & SegSourceBottom) state += 'B';
|
|
|
|
else state += '-';
|
|
|
|
if (_flags & SegTargetTop) state += 'T';
|
|
|
|
else if (_flags & SegTargetBottom) state += 'B';
|
|
|
|
else state += '-';
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
string AutoSegment::_getString () const
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
string s = base()->_getString();
|
|
|
|
//s.insert ( 1, "id: " );
|
|
|
|
//s.insert ( 4, getString(_id) );
|
|
|
|
s.insert ( s.size()-1, _getStringFlags() );
|
2010-03-09 09:24:29 -06:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Record* AutoSegment::_getRecord () const
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
Record* record = base()->_getRecord ();
|
|
|
|
record->add ( getSlot ( "_gcell" , _gcell ) );
|
|
|
|
record->add ( getSlot ( "_id" , &_id ) );
|
|
|
|
record->add ( getSlot ( "_flags" , &_flags ) );
|
|
|
|
record->add ( getSlot ( "_userContraints", &_userConstraints ) );
|
|
|
|
record->add ( getSlot ( "_sourcePosition", &_sourcePosition ) );
|
|
|
|
record->add ( getSlot ( "_targetPosition", &_targetPosition ) );
|
|
|
|
record->add ( getSlot ( "_parent" , _parent ) );
|
2010-03-09 09:24:29 -06:00
|
|
|
return record;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegment* AutoSegment::create ( AutoContact* source
|
|
|
|
, AutoContact* target
|
|
|
|
, Segment* hurricaneSegment
|
|
|
|
)
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
static const Layer* horizontalLayer = Session::getRoutingLayer( 1 );
|
|
|
|
static const Layer* verticalLayer = Session::getRoutingLayer( 2 );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool reattachSource = false;
|
|
|
|
bool reattachTarget = false;
|
2010-03-09 09:24:29 -06:00
|
|
|
AutoSegment* segment;
|
2013-12-03 18:58:58 -06:00
|
|
|
Horizontal* horizontal = dynamic_cast<Horizontal*>( hurricaneSegment );
|
|
|
|
Vertical* vertical = dynamic_cast<Vertical* >( hurricaneSegment );
|
|
|
|
AutoContact* reference = source;
|
|
|
|
|
|
|
|
ltrace(159) << "Source:" << source << endl;
|
|
|
|
ltrace(159) << "Target:" << target << endl;
|
|
|
|
|
|
|
|
if (target->isFixed()) {
|
|
|
|
if (source->isFixed()) {
|
|
|
|
if ( (horizontal) and (source->getY() != target->getY()))
|
|
|
|
cerr << Warning( "Straight AutoHorizontal connecting misaligned contacts:\n"
|
|
|
|
" %s\n"
|
|
|
|
" %s"
|
|
|
|
, getString(source).c_str()
|
|
|
|
, getString(target).c_str()
|
|
|
|
) << endl;
|
|
|
|
if ( (vertical) and (source->getX() != target->getX()))
|
|
|
|
cerr << Warning( "Straight AutoVertical connecting misaligned contacts:\n"
|
|
|
|
" %s\n"
|
|
|
|
" %s"
|
|
|
|
, getString(source).c_str()
|
|
|
|
, getString(target).c_str()
|
|
|
|
) << endl;
|
|
|
|
} else
|
|
|
|
reference = target;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
Contact* contact = dynamic_cast<Contact*>( hurricaneSegment->getSource() );
|
|
|
|
AutoContact* autoContact = Session::lookup( contact );
|
|
|
|
if (contact == NULL) {
|
|
|
|
throw Error( badSegmentSource, getString(hurricaneSegment).c_str() );
|
|
|
|
if ( autoContact and (autoContact != source) )
|
|
|
|
throw Error( mismatchSegmentSource
|
|
|
|
, getString(hurricaneSegment).c_str()
|
|
|
|
, getString(contact).c_str() );
|
|
|
|
} else {
|
|
|
|
if (autoContact != source) reattachSource = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
contact = dynamic_cast<Contact*>( hurricaneSegment->getTarget() );
|
|
|
|
autoContact = Session::lookup( contact );
|
|
|
|
if (contact == NULL) {
|
|
|
|
throw Error( badSegmentTarget, getString(hurricaneSegment).c_str() );
|
|
|
|
if ( autoContact and (autoContact != target) )
|
2010-03-09 09:24:29 -06:00
|
|
|
throw Error ( mismatchSegmentTarget
|
|
|
|
, getString(hurricaneSegment).c_str()
|
|
|
|
, getString(contact).c_str() );
|
2013-12-03 18:58:58 -06:00
|
|
|
} else {
|
|
|
|
if (autoContact != source) reattachTarget = true;
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (reattachSource) {
|
|
|
|
Hook* hook = hurricaneSegment->getSourceHook();
|
|
|
|
hook->detach ();
|
|
|
|
hook->attach ( source->getBodyHook() );
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (reattachTarget) {
|
|
|
|
Hook* hook = hurricaneSegment->getTargetHook();
|
|
|
|
hook->detach ();
|
|
|
|
hook->attach ( target->getBodyHook() );
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (horizontal) {
|
|
|
|
if (horizontal->getLayer() != horizontalLayer) {
|
|
|
|
if ( not Session::getKatabatic()->isGMetal(horizontal->getLayer()) )
|
2010-03-09 09:24:29 -06:00
|
|
|
cerr << Warning("Segment %s forced to %s."
|
|
|
|
,getString(horizontal).c_str()
|
|
|
|
,getString(horizontalLayer).c_str()) << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
horizontal->setLayer( horizontalLayer );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
horizontal->setY( reference->getY() );
|
|
|
|
segment = new AutoHorizontal ( horizontal );
|
|
|
|
segment->_postCreate();
|
|
|
|
} else if (vertical) {
|
|
|
|
if (vertical->getLayer() != verticalLayer) {
|
|
|
|
if ( not Session::getKatabatic()->isGMetal(vertical->getLayer()) )
|
2010-03-09 09:24:29 -06:00
|
|
|
cerr << Warning("Segment %s forced to %s."
|
|
|
|
,getString(vertical).c_str()
|
|
|
|
,getString(verticalLayer).c_str()) << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
vertical->setLayer( verticalLayer );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
vertical->setX( reference->getX() );
|
|
|
|
segment = new AutoVertical ( vertical );
|
|
|
|
segment->_postCreate();
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
throw Error( badSegment, getString(source).c_str(), getString(target).c_str() );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AutoSegment* AutoSegment::create ( AutoContact* source
|
|
|
|
, AutoContact* target
|
|
|
|
, unsigned int dir
|
|
|
|
)
|
|
|
|
{
|
2013-12-03 18:58:58 -06:00
|
|
|
static const Layer* horizontalLayer = Session::getRoutingLayer( 1 );
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
static DbU::Unit horizontalWidth = Session::getWireWidth ( 1 );
|
2013-12-03 18:58:58 -06:00
|
|
|
static const Layer* verticalLayer = Session::getRoutingLayer( 2 );
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
static DbU::Unit verticalWidth = Session::getWireWidth ( 2 );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
AutoSegment* segment;
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoContact* reference = source;
|
|
|
|
|
|
|
|
ltrace(159) << "Source:" << source << endl;
|
|
|
|
ltrace(159) << "Target:" << target << endl;
|
|
|
|
|
|
|
|
if (target->isFixed()) {
|
|
|
|
if (source->isFixed()) {
|
|
|
|
if ( (dir == KbHorizontal) and (source->getY() != target->getY()))
|
|
|
|
cerr << Warning( "Straight AutoHorizontal connecting misaligned contacts:\n"
|
|
|
|
" %s\n"
|
|
|
|
" %s"
|
|
|
|
, getString(source).c_str()
|
|
|
|
, getString(target).c_str()
|
|
|
|
) << endl;
|
|
|
|
if ( (dir == KbVertical) and (source->getX() != target->getX()))
|
|
|
|
cerr << Warning( "Straight AutoVertical connecting misaligned contacts:\n"
|
|
|
|
" %s\n"
|
|
|
|
" %s"
|
|
|
|
, getString(source).c_str()
|
|
|
|
, getString(target).c_str()
|
|
|
|
) << endl;
|
|
|
|
} else
|
|
|
|
reference = target;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dir & KbHorizontal) {
|
|
|
|
segment = create( source
|
|
|
|
, target
|
|
|
|
, Horizontal::create( source->base()
|
|
|
|
, target->base()
|
|
|
|
, horizontalLayer
|
|
|
|
, reference->getY()
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
, horizontalWidth ) );
|
2013-12-03 18:58:58 -06:00
|
|
|
} else if (dir & KbVertical) {
|
|
|
|
segment = create( source
|
|
|
|
, target
|
|
|
|
, Vertical::create( source->base()
|
|
|
|
, target->base()
|
|
|
|
, verticalLayer
|
|
|
|
, reference->getX()
|
Improved UpdateSession & exception catching. Start of RoutingGauge implem.
Miscellaneous:
* Change: In <crlcore>, in display.conf use the same display threshold
for both METAL2 & METAL3.
In alliance.conf, the side of VIAs in the gauge is 2l (not 3l).
In kite.conf, separate edge densities for H/V.
* Change: In <Cell>, in flattenNets() use flag as argument, not a
boolean. Do not create rings for clock or supply nets.
* Change: In <DeepNet>, in _createRoutingPads() do not create rings
for clock or supply net (duplicated policy as in Cell::flattenNets()).
* Bug: In <ControllerWidget>, at last find the bad signal disconnect
that was causing ungraceful messages.
* Change: In <knik>, in Edge display occupancy/capacity in the string
name. Improved display progress and debugging capabilities.
Improved exception catch & breakpoint managment:
* Bug: In <PaletteWidget>, in updateExtensions() replace the calls to
deleteLayer() by delete. This cause the widget to be immediatly
erased instead of waiting for the event queue to be completly
processed. This was causing the widget to be left in a incoherent
state when stoping at a breakpoint.
* Bug: In <BreakpointWidget>, in execNoModal(), flush the main event
loop (QApplication::flush()) *before* lauching the *local* event
loop. This is to ensure all widgets are in their final state when
waiting (especially <PaletteWidget>).
* Change: In <ExceptionWidget>, new method catchAllWrapper() to
execute any std::function< void() > function/method with a "try"/
"catch" wraparound and lauch the widget in case something is catch.
* New: In <hurricane>, support for a oberver pattern, backported from
<katabatic> with an Obervable capable of being linked to any
number of Obervers.
* New: In <Cell>, made it observable to detect Cell change, currently
emit two kind of signals:
- Cell::CellAboutToChange : *before* any change.
- Cell::CellChanged : *after* the change has been completed.
* New: In <UpdateSession>, in Go::invalidate() add the Cell owning the
Go to the UPDATOR_STACK (of course the cell is added only once).
In addition, when the Cell is added, send a notification of
Cell::CellAboutToChange to all it's observers. The slave instances
are also invalidated.
Conversely in UpdateSession::_preDestroy() for each invalidated
Cell send a Cell::CellChanged notification to all observer.
The UPDATOR_STACK has been slightly amended to accept Cell which
are not Gos. Prior to this, the Cell where completly excluded from
the UpdateSession mechanism, so it's instances where never actualised
of anything referring to the Cell for that matter.
Note: we use two different mechanisms to transmit a Cell change,
observers and the slave instance map. I think at some point it
should be unificated.
* Change: In <CellViewer>, make it a Cell observer to redraw when the
cell is modificated (also update the palette).
Uses the catchAllWrapper() to protect all critical actions.
* Change: In <GraphicTool>, no longer need of cellPreModificated and
cellPostModificated signals. Now done through the Cell obersvers.
* Change: In <mauka>, <etesian> & <kite> now uses the catchAllWrapper
method for protection (need to split methods in two, to be able
to pass it as argument). No longer emit cellPreModificated and
cellPostModificated.
Support for RoutingGauge in P&R:
* Bug: In <placeandroute.py>, the connection from the internal power
ring to the connectors was not done correctly. Wrong contact layers
leading to a gap.
* Change: In <BuildPowerRails>, detection of the corona signals based
on how the "pck_px" pad is connected. No longer based on name
matching.
* Change: In <placeandroute.py>, support for 2 routing metal only
(3 metal in the technology).
* Change: In <katabatic> & <kite> support for a "top layer" limitation
on the routing gauge, this allows to use only two routing metals
(METAL2 & METAL3). Work in progress.
2014-04-20 12:25:08 -05:00
|
|
|
, verticalWidth
|
2013-12-03 18:58:58 -06:00
|
|
|
) );
|
2010-03-09 09:24:29 -06:00
|
|
|
} else
|
2013-12-03 18:58:58 -06:00
|
|
|
throw Error( badSegment, getString(source).c_str(), getString(target).c_str() );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return segment;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AutoSegment::destroy ()
|
|
|
|
{
|
|
|
|
_preDestroy ();
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
bool AutoSegment::isTopologicalBound ( AutoSegment* seed, unsigned int flags )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
|
|
|
ltrace(80) << "isTopologicalBound() - " << seed << endl;
|
|
|
|
ltracein(80);
|
|
|
|
|
|
|
|
set<AutoContact*> exploreds;
|
|
|
|
vector<AutoContact*> stack;
|
|
|
|
DbU::Unit axis;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (flags & KbSuperior) axis = seed->getTargetU();
|
|
|
|
else axis = seed->getSourceU();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ltrace(80) << "check for bound " << DbU::getValueString(axis) << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
exploreds.insert( seed->getAutoSource() );
|
|
|
|
exploreds.insert( seed->getAutoTarget() );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (seed->getLength()) {
|
|
|
|
if (flags & KbSuperior) stack.push_back( seed->getAutoTarget() );
|
|
|
|
else stack.push_back( seed->getAutoSource() );
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
stack.push_back( seed->getAutoTarget() );
|
|
|
|
stack.push_back( seed->getAutoSource() );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
while ( not stack.empty() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
AutoContact* currentContact = stack.back();
|
2013-12-03 18:58:58 -06:00
|
|
|
stack.pop_back();
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
ltrace(80) << "Exploring: " << (void*)currentContact << " " << currentContact << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
exploreds.insert( currentContact );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (currentContact->getAnchor()) { ltraceout(80); return true; }
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
forEach ( Component*, component, currentContact->getSlaveComponents() ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
Segment* segment = dynamic_cast<Segment*>( *component );
|
|
|
|
if (not segment) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoSegment* autoSegment = Session::lookup( segment );
|
|
|
|
if (not autoSegment) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (not autoSegment->getLength()) {
|
2010-03-09 09:24:29 -06:00
|
|
|
AutoContact* contact = autoSegment->getAutoSource();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (contact and (contact != currentContact)) {
|
|
|
|
if (exploreds.find(contact) == exploreds.end())
|
|
|
|
stack.push_back( contact );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
contact = autoSegment->getAutoTarget();
|
2013-12-03 18:58:58 -06:00
|
|
|
if (contact and (contact != currentContact)) {
|
|
|
|
if (exploreds.find(contact) == exploreds.end())
|
|
|
|
stack.push_back( contact );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (autoSegment->isHorizontal() xor (flags & KbHorizontal)) continue;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
ltrace(80) << "| " << autoSegment << endl;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (flags & KbSuperior) {
|
|
|
|
if (autoSegment->getTargetU() > axis) { ltraceout(80); return true; }
|
2010-03-09 09:24:29 -06:00
|
|
|
} else {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (autoSegment->getSourceU() < axis) { ltraceout(80); return true; }
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(80);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
#if THIS_IS_DISABLED
|
2010-03-09 09:24:29 -06:00
|
|
|
unsigned int AutoSegment::getPerpandicularState ( AutoContact* contact
|
|
|
|
, AutoSegment* source
|
|
|
|
, AutoSegment* current
|
|
|
|
, bool isHorizontalMaster
|
|
|
|
, const Layer* masterLayer )
|
|
|
|
{
|
|
|
|
unsigned int state = 0;
|
|
|
|
|
|
|
|
bool sourcePerpandicular = arePerpandiculars ( isHorizontalMaster, source );
|
|
|
|
bool currentPerpandicular = arePerpandiculars ( isHorizontalMaster, current );
|
|
|
|
bool contactAlignate
|
|
|
|
= (contact->isHAlignate() and current->isHorizontal() and isHorizontalMaster)
|
|
|
|
or (contact->isVAlignate() and !current->isHorizontal() and !isHorizontalMaster);
|
|
|
|
|
|
|
|
if ( not currentPerpandicular and masterLayer and (masterLayer != current->getLayer()) )
|
|
|
|
state |= ParallelAndLayerChange;
|
|
|
|
|
|
|
|
if ( currentPerpandicular and !current->isCollapsed() )
|
|
|
|
state |= PerpandicularAny;
|
|
|
|
|
|
|
|
if ( sourcePerpandicular ) {
|
|
|
|
// Source segment is perpandicular to master.
|
|
|
|
if ( currentPerpandicular and !current->isCollapsed() )
|
|
|
|
state |= PerpandicularIndirect;
|
|
|
|
} else {
|
|
|
|
// Source segment is parallel to master.
|
|
|
|
if ( not (currentPerpandicular and current->isCollapsed()) and not contactAlignate ) {
|
|
|
|
// Current segment is parallel OR expanded.
|
|
|
|
state |= ParallelOrExpanded;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
#endif
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
|
|
|
|
void AutoSegment::getTopologicalInfos ( AutoSegment* seed
|
2013-12-03 18:58:58 -06:00
|
|
|
, vector<AutoSegment*>& aligneds
|
2010-03-09 09:24:29 -06:00
|
|
|
, vector<AutoSegment*>& perpandiculars
|
|
|
|
, DbU::Unit& leftBound
|
|
|
|
, DbU::Unit& rightBound
|
|
|
|
)
|
|
|
|
{
|
|
|
|
ltrace(80) << "getTopologicalInfos() - " << seed << endl;
|
2013-12-03 18:58:58 -06:00
|
|
|
ltracein(80);
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
leftBound = DbU::Max;
|
|
|
|
rightBound = DbU::Min;
|
|
|
|
|
|
|
|
AutoSegmentStack stack;
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
stack.push( seed->getAutoSource(), seed );
|
|
|
|
stack.push( seed->getAutoTarget(), seed );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
2011-01-09 12:08:31 -06:00
|
|
|
while ( not stack.isEmpty() ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
AutoContact* sourceContact = stack.getAutoContact();
|
|
|
|
AutoSegment* sourceSegment = stack.getAutoSegment();
|
|
|
|
|
|
|
|
stack.pop();
|
|
|
|
|
|
|
|
DbU::Unit constraint;
|
|
|
|
|
|
|
|
if (seed->isHorizontal()) constraint = sourceContact->getCBXMax();
|
|
|
|
else constraint = sourceContact->getCBYMax();
|
|
|
|
if (constraint < leftBound) leftBound = constraint;
|
|
|
|
|
|
|
|
if (seed->isHorizontal()) constraint = sourceContact->getCBXMin();
|
|
|
|
else constraint = sourceContact->getCBYMin();
|
|
|
|
if (constraint > rightBound) rightBound = constraint;
|
|
|
|
|
|
|
|
ltrace(200) << "Segments of: " << sourceContact << endl;
|
|
|
|
LocatorHelper helper (sourceContact, KbHorizontal|KbWithPerpands);
|
|
|
|
for ( ; helper.isValid() ; helper.progress() ) {
|
|
|
|
AutoSegment* currentSegment = helper.getSegment();
|
|
|
|
ltrace(200) << "Looking for: " << currentSegment << endl;
|
|
|
|
if (currentSegment == sourceSegment) continue;
|
|
|
|
|
|
|
|
if (AutoSegment::areAlignedsAndDiffLayer(currentSegment,seed)) {
|
|
|
|
cerr << Error("Aligned segments not in same layer\n"
|
|
|
|
" %s\n"
|
|
|
|
" %s."
|
|
|
|
,getString(seed).c_str()
|
|
|
|
,getString(currentSegment).c_str()) << endl;
|
2010-03-09 09:24:29 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-12-03 18:58:58 -06:00
|
|
|
if (AutoSegment::areAligneds(currentSegment,seed)) {
|
|
|
|
aligneds.push_back( currentSegment );
|
|
|
|
|
|
|
|
AutoContact* targetContact = currentSegment->getOppositeAnchor( sourceContact );
|
|
|
|
ltrace(200) << "Target: " << targetContact << endl;
|
|
|
|
if (targetContact) {
|
|
|
|
if ( (seed->isHorizontal() and sourceContact->isHTee())
|
|
|
|
or (seed->isVertical () and sourceContact->isVTee()) ) {
|
|
|
|
ltrace(200) << "Stacking target. " << endl;
|
|
|
|
stack.push( targetContact, currentSegment );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ltrace(200) << "| perpandicular " << currentSegment << endl;
|
|
|
|
perpandiculars.push_back( currentSegment );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
|
|
|
|
ltraceout(80);
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int AutoSegment::getTerminalCount ( AutoSegment* seed, vector<AutoSegment*>& collapseds )
|
|
|
|
{
|
|
|
|
ltrace(80) << "getTerminalCount() - " << seed << " (+collapseds)" << endl;
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
for ( size_t i=0 ; i < collapseds.size() ; i++ ) {
|
2013-12-03 18:58:58 -06:00
|
|
|
if (collapseds[i]->isStrongTerminal())
|
2010-03-09 09:24:29 -06:00
|
|
|
count++;
|
|
|
|
}
|
2013-12-03 18:58:58 -06:00
|
|
|
if (seed->getAutoSource()->isTerminal()) count++;
|
|
|
|
if (seed->getAutoTarget()->isTerminal()) count++;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // End of Katabatic namespace.
|