Upgrade of Katana detailed router to support Arlet 6502.
* Change: In Hurricane::SharedName, replace the incremental Id by a hash key. This is to ensure better deterministic properties. Between use cases, additional strings may have to be allocated, shitfing the ids. Even if hash can be duplicated, we should be able to ensure that the absolute order in map table should be preserved. Supplemental strings are inserted in a way that keep the previous order. * Change: In CRL/etc/symbolic/cmos/kite.conf, add "katabatic.routingGauge" default parameter value ("sxlib"). * Change: In CRL/etc/common/technology.conf, define minimal spacing for symbolic layers too (added for METAL4 only for now). * Change: In CRL::Histogram, extend support to dynamically sized histograms. Add a text pretty print with table and pseudo-curve. * Change: In Cumulus/plugins/ClockTreePlugin, create blockage under the block corona corners so the global router do not draw wire under them. This was creating deadlock for the detailed router. When the abutment has to be computed, directly use Etesian to do it instead of duplicating the computation in the Python plugin. * New: In Etesian, as Coloquinte seems reluctant to evenly spread the standard cells, we trick it by making them bigger during the placement stage. Furthermore, we do not not uniformely increase the size of the cells but create a "bloating profile" based on cell size, cell name or it's density of terminals. Currently only two profiles are defined, "disabled" which does nothing and "nsxlib" targeted on 4 metal layer technologies (aka AMS 350nm, c35b4). * Bug: In Knik::MatrixVertex, load the default routing gauge using the configuration parameter "katabatic.routingGauge" as the default one may not be the first registered one. * New: In AnabaticEngine::setupNetDatas(), build a dynamic historgram of the nets terminal numbers. * Bug: In Anabatic::AutoContact::Invalidate(), always invalidate the contact cache when topology is invalidated. In case of multiple invalidations, if the first did not invalidate the cache, later one that may need it where not allowed to do so. The end result was correct nonetheless, but it did generate annoying error messages. * Bug: In Anabatic::AutoContactTurn::updateTopology(), bad computation of the contact's depth when delta == 2. * Bug: In Anabatic::Gcell::getCapacity(), was always returning the west edge capacity, even for the westermost GCell, should be the east edge in that case. * New: In Anabatic::AutoSegment, introduce a new measure "distance to terminal". This is the minimal number of segments separating the current one from the nearest RoutingPad. This replace the previous "strong terminal" and "weak terminal" flags. This distance is used by Katana to sort the events, we route the segments *from* the RoutingPads *outward*. The idea being that if we cannot event connect to the RoutingPad, there is no points continuing as thoses segments are the more constraineds. This gives an order close to the simple ascending metals but with better results. * New: In Anabatic::AutoSegment, introduce a new flag "Unbreakable", disable dogleg making on those segments. mainly intended for local segments directly connecteds to RoutingPads (distance == 0). * New: In Anabatic::AutoSegment, more aggressive reducing of segments. Now the only case where a segment cannot be reduced is when it is one horizontal branch in a HTee or a vertical on a VTee. Check if, when not accounted the source & target VIAs are still connex, if so, allow reducing. * New: In Anabatic::AutoContact, new state flags CntVDogleg & CntHDogleg mainly to prevent making doglegs twice on a turn contact. This is to limit over-fragmentation. If one dogleg doesn't solve the problem, making a second one will make things worse only... * Bug: In Anabatic::Configuration::selectRpcomponent(), we were choosing the component with the *smallest* span instead of the *bigger* one. * New: In Anabatic::GCell, introduce a new flag "GoStraight" to tell that no turn go be made inside those GCells. Mainly used underneath a block corona. * New: In AnabaticEngine::layerAssign(), new GCellRps & RpsInRow to manage GCells with too many terminals. Slacken at least one RoutingPad access when there is more than 8 RoutingPad in the GCell (slacken or change a vertical METAL2 (non-preferred) into a METAL3). * Change: In Anabatic::NetBuilderHV, allow the use of terminal connection in non-preferred direction. That is, vertical METAL2 directly connected to the RoutingPad (then a horizontal METAL2). This alllows for short dogleg without clutering the METAL3 layer (critical for AMS c35b4). Done in NetBuilderHV::doRp_Access(), with a new UseNonPref flag. Perform some other tweaking on METAL1 access topologies, to also minimize METAL3 use. * New: In AnabaticEngine::computeNetConstraints(), also compute the distance to RoutingPad for segments. Set the Unbreakable flag, based on the distance and segment length (local, short global or long global). New local function "propagateDistanceFromRp()". * Change: In AnabaticEngine.h, the sorting class for NetData, SparsityOrder, is modificated so net with a degree superior to 10 are sorted first, whatever their sparsity. This is to work in tandem with GlobalRouting. * New: In Katana::TrackSegmentNonPref, introduce a class to manage segment in non-preferred routing direction. Mostly intended for small METAL2 vertical directly connected to RoutingPad. Modifications to manage this new variant all through Katana. * Change: In Katana::GlobalRoute, DigitalDistance honor the GoStraight flag of the GCell. Do not make bend inside thoses GCells. * Change: In KatanaEngine::runGlobalRouter(), high degree nets (>= 10) are routed first and whitout the global routing estimation. There should be few of them so they wont create saturations and we want them as straight as possible. Detour are for long be-points. Set the saerch halo to one GCell in the initial routing stage (before ripup). * Bug: In KatanaEngine & NegociateWindow, call _computeCagedconstraints() inside NegociateWindow::run(), as segments are inserted into tracks only at that point so we cannot make the computation earlier. * Change: In Katana::Manipulator::repackPerpandiculars(), add a flag to select whether to replace the perpandiculars *after* or *before* the current segment. * Change: In Katana::NegociateWindow::NegociateOverlapCost(), when the segment is fully enclosed inside a global, the longest overlap cost is set to the shortest global hoverhang (before or after). When the cost is for a global, set an infinite cost if the overlapping segment has a RP distance less or equal to 1 (this is an access segment). * Bug: In Katana::PowerRailsPlane::Rail::doLayout(), correct computation of the segments extension cap. * New: In Katana::QueryPowerRails::addToPowerRail(), add support for Pad. * Change: In Katana/PreProcess::protectCagedTerminals(), apply the contraints to any turn connected to the first segment of the RoutingPad so the perpandicular constraints got propagated to the perpandicular segment... * Change: In RoutingEvent, cache the "distance to RP" value. * Change: In RoutingEvent::Key::compare(), sort *first* on distance to RoutingPad, then layer depth. If both distance to RoutingPad is null, then sort on segment length. * Change: In RoutingEvent::_processRepair(), try a repack perpandicular with perpandiculars first (then with perpandicular last, then give up). * Change: In SegmentFsm::bindToTrack() and moveToTrack(), set an axis hint when creating the insertion event. * Change: In SegmentFsm::_slackenStrap(), add a step through slacken between minimize and maximum slack (wihch directly end up in unimplemented). * Change: In Session::_addInsertEvent(), add an axis parameter needed when the axis of the segment is not the one of the track (case of wide segments or non-preferred direction). * Bug: In Track::_preDestroy(), bad management of the TrackElement reference count. Destroy the segment only when reaching zero... * Bug: In Track::expandFreeIneterval(), forgotten to manage case when there is a set of overlaping segments at the "end" of the track, the EndIsTrackMax was not set. * Change: In TrackCost::Compare, increase the cost when an overlaping segment is at it's ripup limit. We should try *not* to rip it up if we can. Add a dedicated flag "AtRipupLimit". * Change: In TrackElement, add proxies for isUnbreakable(), new function updateTrackSpan(). * New: In TrackFixedSegment CTOR, when a supply wire of METAL2 or above is found, make the underlying GCells "GoStraight". * New: In TrackElement::canDogleg(GCell*), check for already done perpandicular dogleg on source/target (reject if so).
This commit is contained in:
parent
bc88fe0075
commit
f528cdea4c
|
@ -29,6 +29,7 @@
|
|||
#include "hurricane/UpdateSession.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "crlcore/Measures.h"
|
||||
#include "crlcore/Histogram.h"
|
||||
#include "anabatic/GCell.h"
|
||||
#include "anabatic/AutoContactTerminal.h"
|
||||
#include "anabatic/NetBuilderM2.h"
|
||||
|
@ -145,6 +146,7 @@ namespace Anabatic {
|
|||
using CRL::RoutingLayerGauge;
|
||||
using CRL::addMeasure;
|
||||
using CRL::getMeasure;
|
||||
using CRL::Histogram;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -489,10 +491,18 @@ namespace Anabatic {
|
|||
|
||||
void AnabaticEngine::setupNetDatas ()
|
||||
{
|
||||
Histogram netHistogram ( 0.0, 1.0, 1 );
|
||||
netHistogram.setTitle ( "RoutingPads", 0 );
|
||||
netHistogram.setColor ( "green" , 0 );
|
||||
netHistogram.setIndent( " " , 0 );
|
||||
|
||||
size_t oindex = _netOrdering.size();
|
||||
for ( Net* net : _cell->getNets() ) {
|
||||
if (_netDatas.find(net->getId()) != _netDatas.end()) continue;
|
||||
_netOrdering.push_back( new NetData(net) );
|
||||
NetData* data = new NetData( net );
|
||||
_netOrdering.push_back( data );
|
||||
|
||||
netHistogram.addSample( (float)data->getRpCount(), 0 );
|
||||
}
|
||||
|
||||
for ( ; oindex < _netOrdering.size() ; ++oindex ) {
|
||||
|
@ -501,6 +511,9 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
sort( _netOrdering.begin(), _netOrdering.end(), SparsityOrder() );
|
||||
|
||||
cmess2 << " o Nets Histogram." << endl;
|
||||
cmess2 << netHistogram.toString(0) << endl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -274,11 +274,11 @@ namespace Anabatic {
|
|||
|
||||
void AutoContact::invalidate ( Flags flags )
|
||||
{
|
||||
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
|
||||
if (not isInvalidated()) {
|
||||
cdebug_log(145,1) << "AutoContact::invalidate() - " << this << endl;
|
||||
cdebug_log(145,0) << "flags:" << flags.asString(FlagsFunction) << endl;
|
||||
setFlags( CntInvalidated );
|
||||
if (flags & Flags::Topology ) setFlags( CntInvalidatedCache );
|
||||
Session::invalidate( this );
|
||||
|
||||
_invalidate( flags );
|
||||
|
@ -554,6 +554,9 @@ namespace Anabatic {
|
|||
|
||||
void AutoContact::setLayerAndWidth ( size_t delta, size_t depth )
|
||||
{
|
||||
cdebug_log(145,1) << "AutoContact::setLayerAndWidth() " << this << endl;
|
||||
cdebug_log(145,0) << "delta:" << delta << " depth:" << depth << endl;
|
||||
|
||||
if (delta == 0) {
|
||||
setLayer( Session::getRoutingLayer(depth) );
|
||||
setSizes( Session::getWireWidth (depth)
|
||||
|
@ -563,6 +566,8 @@ namespace Anabatic {
|
|||
setSizes( Session::getViaWidth (depth)
|
||||
, Session::getViaWidth (depth) );
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -337,7 +337,7 @@ namespace Anabatic {
|
|||
void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
|
||||
{
|
||||
if (_segment == segment) {
|
||||
_segment->unsetFlags( AutoSegment::SegAxisSet );
|
||||
//_segment->unsetFlags( AutoSegment::SegAxisSet );
|
||||
_segment = NULL;
|
||||
setFlags( CntInvalidatedCache );
|
||||
unsetFlags( CntDrag );
|
||||
|
|
|
@ -239,7 +239,7 @@ namespace Anabatic {
|
|||
RoutingGauge* rg = Session::getRoutingGauge();
|
||||
size_t depthH1 = rg->getLayerDepth( getHorizontal1()->getLayer() );
|
||||
size_t depthV1 = rg->getLayerDepth( getVertical1 ()->getLayer() );
|
||||
size_t depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
|
||||
size_t depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
|
||||
size_t delta = abssub ( depthH1, depthV1 );
|
||||
|
||||
unsetFlags( CntWeakTerminal );
|
||||
|
@ -247,7 +247,7 @@ namespace Anabatic {
|
|||
showTopologyError( "Sheared Turn, layer delta exceed 3." );
|
||||
setFlags( CntBadTopology );
|
||||
} else {
|
||||
if (delta == 3) {
|
||||
if (delta > 1) {
|
||||
if (_horizontal1->isInvalidatedLayer()) {
|
||||
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
||||
_horizontal1->makeDogleg(this);
|
||||
|
@ -259,7 +259,7 @@ namespace Anabatic {
|
|||
}
|
||||
depthH1 = rg->getLayerDepth( _horizontal1->getLayer() );
|
||||
depthV1 = rg->getLayerDepth( _vertical1->getLayer() );
|
||||
depthContact = (depthH1 < depthV1) ? depthH1 : depthH1-1;
|
||||
depthContact = (depthH1 <= depthV1) ? depthH1 : depthH1-1;
|
||||
delta = abssub ( depthH1, depthV1 );
|
||||
}
|
||||
|
||||
|
|
|
@ -831,27 +831,62 @@ namespace Anabatic {
|
|||
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
||||
Session::dogleg( segment2 );
|
||||
|
||||
if (autoSource->isTerminal()) {
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegWeakTerminal1 );
|
||||
if (autoSource->isTerminal() and autoTarget->isTerminal()) {
|
||||
segment1->setRpDistance( 1 );
|
||||
segment2->setRpDistance( 0 );
|
||||
dlContact1->setFlags ( CntWeakTerminal );
|
||||
dlContact2->setFlags ( CntWeakTerminal );
|
||||
|
||||
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
|
||||
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (autoSource->isTerminal()) {
|
||||
segment1->setRpDistance( 1 );
|
||||
segment2->setRpDistance( 2 );
|
||||
|
||||
autoTarget->unsetFlags( CntWeakTerminal );
|
||||
dlContact1->setFlags ( CntWeakTerminal );
|
||||
if (autoTarget->getGCell() == doglegGCell)
|
||||
dlContact1->migrateConstraintBox( autoTarget );
|
||||
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
|
||||
} else if (autoTarget->isTerminal()) {
|
||||
segment2->setRpDistance( 0 );
|
||||
segment1->setRpDistance( 1 );
|
||||
setRpDistance( 2 );
|
||||
|
||||
unsetFlags( SegTargetTerminal );
|
||||
setFlags( SegWeakTerminal1 );
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegTargetTerminal );
|
||||
autoSource->unsetFlags( CntWeakTerminal );
|
||||
dlContact2->setFlags ( CntWeakTerminal );
|
||||
if (autoSource->getGCell() == doglegGCell)
|
||||
dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (isWeakTerminal()) {
|
||||
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (isWeakTerminal()) {
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegWeakTerminal1 );
|
||||
segment1->setRpDistance( getRpDistance() );
|
||||
segment2->setRpDistance( getRpDistance() );
|
||||
} else {
|
||||
segment1->setRpDistance( getRpDistance() );
|
||||
segment2->setRpDistance( getRpDistance() );
|
||||
}
|
||||
|
||||
// if (autoSource->isTerminal()) {
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegWeakTerminal1 );
|
||||
// autoTarget->unsetFlags( CntWeakTerminal );
|
||||
// dlContact1->setFlags ( CntWeakTerminal );
|
||||
// if (autoTarget->getGCell() == doglegGCell)
|
||||
// dlContact1->migrateConstraintBox( autoTarget );
|
||||
// } else if (autoTarget->isTerminal()) {
|
||||
// unsetFlags( SegTargetTerminal );
|
||||
// setFlags( SegWeakTerminal1 );
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegTargetTerminal );
|
||||
// autoSource->unsetFlags( CntWeakTerminal );
|
||||
// dlContact2->setFlags ( CntWeakTerminal );
|
||||
// if (autoSource->getGCell() == doglegGCell)
|
||||
// dlContact2->migrateConstraintBox( autoSource );
|
||||
// } else if (isWeakTerminal()) {
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegWeakTerminal1 );
|
||||
// }
|
||||
|
||||
if (isAnalog()) {
|
||||
segment1->setFlags( SegAnalog );
|
||||
segment2->setFlags( SegAnalog );
|
||||
|
@ -871,8 +906,11 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntVDogleg );
|
||||
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntVDogleg );
|
||||
|
||||
if (autoTarget->canDrag() and not autoSource->canDrag()) {
|
||||
if (not autoTarget->getGCell()->isDevice()) {
|
||||
if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
|
|
|
@ -472,6 +472,7 @@ namespace Anabatic {
|
|||
, _optimalMin (0)
|
||||
, _optimalMax (0)
|
||||
, _reduceds (0)
|
||||
, _rpDistance (15)
|
||||
, _sourcePosition (0)
|
||||
, _targetPosition (0)
|
||||
, _userConstraints (false)
|
||||
|
@ -687,11 +688,11 @@ namespace Anabatic {
|
|||
|
||||
bool AutoSegment::isStrongTerminal ( Flags flags ) const
|
||||
{
|
||||
if (_flags & SegStrongTerminal) return true;
|
||||
if (isTerminal()) return true;
|
||||
|
||||
if ((flags & Flags::Propagate) and not isNotAligned()) {
|
||||
for ( AutoSegment* segment : const_cast<AutoSegment*>(this)->getAligneds() ) {
|
||||
if (segment->_flags & SegStrongTerminal) return true;
|
||||
if (segment->isTerminal()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -761,8 +762,8 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(145,0) << "AutoSegment::getCanonical() - " << this << endl;
|
||||
|
||||
min = getSourcePosition ();
|
||||
max = getTargetPosition ();
|
||||
min = getSourcePosition();
|
||||
max = getTargetPosition();
|
||||
|
||||
if (max < min) swap( min, max );
|
||||
|
||||
|
@ -775,14 +776,14 @@ namespace Anabatic {
|
|||
DbU::Unit collapsedMax;
|
||||
|
||||
if (not isNotAligned()) {
|
||||
forEach( AutoSegment*, isegment, getAligneds() ) {
|
||||
if (isegment->isCanonical()) {
|
||||
canonical = *isegment;
|
||||
for ( AutoSegment* segment : getAligneds() ) {
|
||||
if (segment->isCanonical()) {
|
||||
canonical = segment;
|
||||
canonicals++;
|
||||
}
|
||||
|
||||
collapsedMin = isegment->getSourcePosition();
|
||||
collapsedMax = isegment->getTargetPosition();
|
||||
collapsedMin = segment->getSourcePosition();
|
||||
collapsedMax = segment->getTargetPosition();
|
||||
if (collapsedMax < collapsedMin) swap( collapsedMin, collapsedMax );
|
||||
if (collapsedMin < min) min = collapsedMin;
|
||||
if (collapsedMax > max) max = collapsedMax;
|
||||
|
@ -799,8 +800,8 @@ namespace Anabatic {
|
|||
|
||||
int count = 0;
|
||||
cerr << " " << count++ << ": " << this << endl;
|
||||
forEach( AutoSegment*, isegment, getAligneds() )
|
||||
cerr << " " << count++ << ": " << *isegment << endl;
|
||||
for ( AutoSegment* segment : getAligneds() )
|
||||
cerr << " " << count++ << ": " << segment << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,6 +1037,10 @@ namespace Anabatic {
|
|||
cdebug_log(149,1) << "toOptimalAxis() " << this << endl;
|
||||
|
||||
if (not isCanonical()) { cdebug_tabw(149,-1); return false; }
|
||||
if (not isUnsetAxis()) {
|
||||
cdebug_tabw(149,-1);
|
||||
return toConstraintAxis( flags );
|
||||
}
|
||||
|
||||
DbU::Unit constraintMin;
|
||||
DbU::Unit constraintMax;
|
||||
|
@ -1539,23 +1544,35 @@ namespace Anabatic {
|
|||
|
||||
bool AutoSegment::canReduce () const
|
||||
{
|
||||
if (isGlobal() or isDrag()) return false;
|
||||
cdebug_log(159,0) << "AutoSegment::canReduce():" << this << endl;
|
||||
cdebug_log(159,0) << " _reduceds:" << _reduceds << endl;
|
||||
|
||||
if (isGlobal() or isDrag() or isFixed()) return false;
|
||||
if (not isSpinTopOrBottom()) return false;
|
||||
if (_reduceds) return false;
|
||||
|
||||
AutoContact* source = getAutoSource();
|
||||
AutoContact* target = getAutoTarget();
|
||||
|
||||
if (not source->isTurn() or not target->isTurn()) return false;
|
||||
cdebug_log(159,0) << " source:" << source->isHTee() << "+" << source->isVTee() << endl;
|
||||
cdebug_log(159,0) << " target:" << target->isHTee() << "+" << target->isVTee() << endl;
|
||||
|
||||
if ( ((source->isHTee() or target->isHTee()) and isHorizontal())
|
||||
or ((source->isVTee() or target->isVTee()) and isVertical ()) ) return false;
|
||||
|
||||
// if ( source->isHTee() or source->isVTee()
|
||||
// or target->isHTee() or target->isVTee() ) return false;
|
||||
|
||||
unsigned int perpandicularDepth = getDepth();
|
||||
if (isSpinBottom()) --perpandicularDepth;
|
||||
else if (isSpinTop()) {
|
||||
if (isSpinBottom()) {
|
||||
if (perpandicularDepth > 0) --perpandicularDepth;
|
||||
} else if (isSpinTop()) {
|
||||
++perpandicularDepth;
|
||||
if (perpandicularDepth >= Session::getDepth()) return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
cdebug_log(159,0) << " length:" << DbU::getValueString(getLength()) << endl;
|
||||
if (getLength() >= (Session::getPitch(perpandicularDepth) * 2)) return false;
|
||||
|
||||
return true;
|
||||
|
@ -1570,8 +1587,17 @@ namespace Anabatic {
|
|||
AutoContact* target = getAutoTarget();
|
||||
|
||||
_flags |= SegIsReduced;
|
||||
source->getPerpandicular( this )->incReduceds();
|
||||
target->getPerpandicular( this )->incReduceds();
|
||||
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
perpandicular->incReduceds();
|
||||
}
|
||||
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
perpandicular->incReduceds();
|
||||
}
|
||||
|
||||
// if (not source->isTerminal()) source->getPerpandicular( this )->incReduceds();
|
||||
// if (not target->isTerminal()) target->getPerpandicular( this )->incReduceds();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1598,8 +1624,16 @@ namespace Anabatic {
|
|||
AutoContact* target = getAutoTarget();
|
||||
|
||||
_flags &= ~SegIsReduced;
|
||||
source->getPerpandicular( this )->decReduceds();
|
||||
target->getPerpandicular( this )->decReduceds();
|
||||
//if (not source->isTerminal()) source->getPerpandicular( this )->decReduceds();
|
||||
//if (not target->isTerminal()) target->getPerpandicular( this )->decReduceds();
|
||||
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
perpandicular->decReduceds();
|
||||
}
|
||||
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
perpandicular->decReduceds();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1607,6 +1641,8 @@ namespace Anabatic {
|
|||
|
||||
void AutoSegment::changeDepth ( unsigned int depth, Flags flags )
|
||||
{
|
||||
DebugSession::open( getNet(), 145, 150 );
|
||||
|
||||
cdebug_log(149,1) << "changeDepth() " << depth << " - " << this << endl;
|
||||
Session::invalidate( getNet() );
|
||||
|
||||
|
@ -1620,6 +1656,8 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
cdebug_tabw(149,-1);
|
||||
|
||||
DebugSession::close();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1632,6 +1670,7 @@ namespace Anabatic {
|
|||
|
||||
const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth);
|
||||
if (getLayer() != newLayer) {
|
||||
cdebug_log(149,0) << "Effective layer change to " << depth << "/" << newLayer << endl;
|
||||
setLayer( depth );
|
||||
getAutoSource()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
||||
getAutoTarget()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
||||
|
@ -1741,7 +1780,7 @@ namespace Anabatic {
|
|||
cdebug_log(149,0) << "AutoSegment::canPivotUp() - " << flags
|
||||
<< " (reserve:" << reserve << ")" << endl;
|
||||
|
||||
if ( isLayerChange() or isFixed() ) return false;
|
||||
if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
|
||||
if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false;
|
||||
if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false;
|
||||
|
||||
|
@ -1790,7 +1829,7 @@ namespace Anabatic {
|
|||
cdebug_log(149,0) << "AutoSegment::canPivotDown()"
|
||||
<< " (reserve:" << reserve << ")" << endl;
|
||||
|
||||
if ( isLayerChange() or isFixed() ) return false;
|
||||
if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
|
||||
if ( isStrongTerminal() or isLocal() ) return false;
|
||||
|
||||
size_t depth = Session::getRoutingGauge()->getLayerDepth( getLayer() );
|
||||
|
@ -1840,7 +1879,7 @@ namespace Anabatic {
|
|||
bool nLowDensity = true;
|
||||
bool nLowUpDensity = true;
|
||||
|
||||
if ( isLayerChange() or isFixed() ) return false;
|
||||
if ( isLayerChange() or isFixed() or isUnbreakable() ) return false;
|
||||
if ( isStrongTerminal() and (not (flags & Flags::AllowTerminal)) ) return false;
|
||||
if ( isLocal() and (not (flags & Flags::AllowLocal )) ) return false;
|
||||
|
||||
|
@ -1952,36 +1991,90 @@ namespace Anabatic {
|
|||
{
|
||||
if (not isReduced()) return true;
|
||||
|
||||
DebugSession::open( getNet(), 149, 160 );
|
||||
cdebug_log(159,1) << "AutoSegment::reduceDoglegLayer(): " << this << endl;
|
||||
|
||||
AutoContact* source = getAutoSource();
|
||||
AutoContact* target = getAutoTarget();
|
||||
|
||||
unsigned int perpandicularDepth = getDepth();
|
||||
if (isSpinBottom()) --perpandicularDepth;
|
||||
if (isSpinTop ()) ++perpandicularDepth;
|
||||
unsigned int minSourceDepth = Session::getAllowedDepth();
|
||||
unsigned int maxSourceDepth = 0;
|
||||
unsigned int minTargetDepth = Session::getAllowedDepth();
|
||||
unsigned int maxTargetDepth = 0;
|
||||
|
||||
if (perpandicularDepth == getDepth()) {
|
||||
cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n"
|
||||
" %s"
|
||||
, getString(this).c_str() ) << endl;
|
||||
return false;
|
||||
if (source->isTerminal()) {
|
||||
unsigned int anchorDepth = Session::getLayerDepth( source->base()->getAnchor()->getLayer() );
|
||||
minSourceDepth = std::min( minSourceDepth, anchorDepth );
|
||||
maxSourceDepth = std::max( maxSourceDepth, anchorDepth );
|
||||
} else {
|
||||
for ( AutoSegment* perpandicular : source->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
minSourceDepth = std::min( minSourceDepth, perpandicular->getDepth() );
|
||||
maxSourceDepth = std::max( maxSourceDepth, perpandicular->getDepth() );
|
||||
}
|
||||
}
|
||||
if (target->isTerminal()) {
|
||||
unsigned int anchorDepth = Session::getLayerDepth( target->base()->getAnchor()->getLayer() );
|
||||
minTargetDepth = std::min( minTargetDepth, anchorDepth );
|
||||
maxTargetDepth = std::max( maxTargetDepth, anchorDepth );
|
||||
} else {
|
||||
for ( AutoSegment* perpandicular : target->getAutoSegments() ) {
|
||||
if (perpandicular == this) continue;
|
||||
minTargetDepth = std::min( minTargetDepth, perpandicular->getDepth() );
|
||||
maxTargetDepth = std::max( maxTargetDepth, perpandicular->getDepth() );
|
||||
}
|
||||
}
|
||||
|
||||
const Layer* layer = Session::getRoutingLayer(perpandicularDepth);
|
||||
DbU::Unit side = Session::getWireWidth (perpandicularDepth);
|
||||
|
||||
source->setLayer( layer );
|
||||
target->setLayer( layer );
|
||||
setLayer( layer );
|
||||
source->setSizes( side, side );
|
||||
target->setSizes( side, side );
|
||||
cdebug_log(159,0) << "Source span: [" << minSourceDepth << " " << maxSourceDepth << "]" << endl;
|
||||
cdebug_log(159,0) << "Target span: [" << minTargetDepth << " " << maxTargetDepth << "]" << endl;
|
||||
|
||||
if ( (minSourceDepth == maxSourceDepth)
|
||||
and (minTargetDepth == maxTargetDepth)
|
||||
and (minTargetDepth == minTargetDepth) ) {
|
||||
const Layer* layer = Session::getRoutingLayer(minSourceDepth);
|
||||
DbU::Unit side = Session::getWireWidth (minSourceDepth);
|
||||
|
||||
cdebug_log(159,0) << "Reducing to " << minSourceDepth << " " << layer << endl;
|
||||
|
||||
source->setLayer( layer );
|
||||
target->setLayer( layer );
|
||||
setLayer( layer );
|
||||
source->setSizes( side, side );
|
||||
target->setSizes( side, side );
|
||||
}
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
DebugSession::close();
|
||||
return true;
|
||||
|
||||
|
||||
// if (not source->isTurn() or not target->isTurn()) return true;
|
||||
|
||||
// unsigned int perpandicularDepth = getDepth();
|
||||
// if (isSpinBottom()) --perpandicularDepth;
|
||||
// if (isSpinTop ()) ++perpandicularDepth;
|
||||
|
||||
// if (perpandicularDepth == getDepth()) {
|
||||
// cerr << Bug( "AutoSegment::reduceDoglegLayer(): Reduced segment spin is neither top (TT) nor bottom (BB).\n"
|
||||
// " %s"
|
||||
// , getString(this).c_str() ) << endl;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// const Layer* layer = Session::getRoutingLayer(perpandicularDepth);
|
||||
// DbU::Unit side = Session::getWireWidth (perpandicularDepth);
|
||||
|
||||
// source->setLayer( layer );
|
||||
// target->setLayer( layer );
|
||||
// setLayer( layer );
|
||||
// source->setSizes( side, side );
|
||||
// target->setSizes( side, side );
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
|
||||
#if THIS_IS_DISABLED
|
||||
|
||||
|
||||
bool AutoSegment::shearUp ( GCell* upGCell, AutoSegment*& movedUp, float reserve, Flags flags )
|
||||
{
|
||||
cdebug_log(149,0) << "AutoSegment::shearUp() " << this << endl;
|
||||
|
@ -2065,11 +2158,11 @@ namespace Anabatic {
|
|||
if (not isNotAligned()) {
|
||||
for ( AutoSegment* segment : getAligneds() ) {
|
||||
if (segment->getSpanU().contains(interval.getVMin())) {
|
||||
if (segment->isFixed()) return false;
|
||||
if (segment->isFixed()) return Flags::NoFlags;
|
||||
leftDogleg++;
|
||||
}
|
||||
if (segment->getSpanU().contains(interval.getVMax())) {
|
||||
if (segment->isFixed()) return 0;
|
||||
if (segment->isFixed()) return Flags::NoFlags;
|
||||
rightDogleg++;
|
||||
}
|
||||
}
|
||||
|
@ -2114,14 +2207,14 @@ namespace Anabatic {
|
|||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
||||
|
||||
if (isSource) {
|
||||
doglegs[ index + 0 ]->setLayer( segmentDepth-2 );
|
||||
doglegs[ index + 0 ]->setLayer( std::max((size_t)1,segmentDepth-2) );
|
||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
||||
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
||||
} else {
|
||||
doglegs[ index + 2 ]->setLayer( segmentDepth-2 );
|
||||
doglegs[ index + 2 ]->setLayer( std::max((size_t)1,segmentDepth-2) );
|
||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
||||
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
||||
|
@ -2262,10 +2355,10 @@ namespace Anabatic {
|
|||
} else {
|
||||
cdebug_log(149,0) << "Looking in aligneds." << endl;
|
||||
if (not isNotAligned()) {
|
||||
forEach ( AutoSegment*, aligned, getAligneds(flags) ) {
|
||||
cdebug_log(149,0) << "| Try in " << *aligned << endl;
|
||||
for ( AutoSegment* aligned : getAligneds(flags) ) {
|
||||
cdebug_log(149,0) << "| Try in " << aligned << endl;
|
||||
if (doglegGCell->getSide(getDirection()).intersect(aligned->getSpanU())) {
|
||||
cdebug_log(149,0) << "Dogleg in " << *aligned << endl;
|
||||
cdebug_log(149,0) << "Dogleg in " << aligned << endl;
|
||||
rflags = aligned->_makeDogleg( doglegGCell, flags );
|
||||
cdebug_tabw(149,-1);
|
||||
return 0;
|
||||
|
@ -2312,6 +2405,7 @@ namespace Anabatic {
|
|||
state += isFixedAxis () ? "X": "-";
|
||||
state += isUnsetAxis () ? "u": "-";
|
||||
state += isStrap () ? "S": "-";
|
||||
state += isUnbreakable () ? "U": "-";
|
||||
state += isCanonical () ? "C": "-";
|
||||
state += isGlobal () ? "G": "-";
|
||||
state += isWeakGlobal () ? "g": "-";
|
||||
|
@ -2341,9 +2435,9 @@ namespace Anabatic {
|
|||
|
||||
string AutoSegment::_getString () const
|
||||
{
|
||||
string s = base()->_getString();
|
||||
//s.insert ( 1, "id: " );
|
||||
//s.insert ( 4, getString(_id) );
|
||||
string sdistance = " rpD:" + getString(_rpDistance);
|
||||
string s = base()->_getString();
|
||||
s.insert ( s.size()-1, sdistance );
|
||||
s.insert ( s.size()-1, _getStringFlags() );
|
||||
return s;
|
||||
}
|
||||
|
@ -2511,6 +2605,19 @@ namespace Anabatic {
|
|||
const Layer* vLayer = Session::getDVerticalLayer();
|
||||
DbU::Unit vWidth = Session::getDVerticalWidth();
|
||||
|
||||
if (dir & Flags::UseNonPref) {
|
||||
if (dir & Flags::Vertical) {
|
||||
cdebug_log(149,0) << "Make vertical in non-preferred direction." << endl;
|
||||
vLayer = hLayer;
|
||||
vWidth = hWidth;
|
||||
}
|
||||
if (dir & Flags::Horizontal) {
|
||||
cdebug_log(149,0) << "Make horizontal in non-preferred direction." << endl;
|
||||
hLayer = vLayer;
|
||||
hWidth = vWidth;
|
||||
}
|
||||
}
|
||||
|
||||
const Layer* horizontalLayer = hLayer;
|
||||
DbU::Unit horizontalWidth = hWidth;
|
||||
const Layer* verticalLayer = vLayer;
|
||||
|
@ -2581,6 +2688,7 @@ namespace Anabatic {
|
|||
|
||||
if (wPitch > 1) segment->setFlags( SegWide );
|
||||
if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag );
|
||||
if (dir & Flags::UseNonPref) segment->setFlags( SegNonPref );
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
|
|
@ -741,27 +741,62 @@ namespace Anabatic {
|
|||
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
||||
Session::dogleg( segment2 );
|
||||
|
||||
if (isSourceTerminal()) {
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegWeakTerminal1 );
|
||||
if (autoSource->isTerminal() and autoTarget->isTerminal()) {
|
||||
segment1->setRpDistance( 1 );
|
||||
segment2->setRpDistance( 0 );
|
||||
dlContact1->setFlags ( CntWeakTerminal );
|
||||
dlContact2->setFlags ( CntWeakTerminal );
|
||||
|
||||
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
|
||||
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (autoSource->isTerminal()) {
|
||||
segment1->setRpDistance( 1 );
|
||||
segment2->setRpDistance( 2 );
|
||||
|
||||
autoTarget->unsetFlags( CntWeakTerminal );
|
||||
dlContact1->setFlags ( CntWeakTerminal );
|
||||
if (autoTarget->getGCell() == doglegGCell)
|
||||
dlContact1->migrateConstraintBox( autoTarget );
|
||||
} else if (isTargetTerminal()) {
|
||||
if (autoTarget->getGCell() == doglegGCell) dlContact1->migrateConstraintBox( autoTarget );
|
||||
} else if (autoTarget->isTerminal()) {
|
||||
segment2->setRpDistance( 0 );
|
||||
segment1->setRpDistance( 1 );
|
||||
setRpDistance( 2 );
|
||||
|
||||
unsetFlags( SegTargetTerminal );
|
||||
setFlags( SegWeakTerminal1 );
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegTargetTerminal );
|
||||
autoSource->unsetFlags( CntWeakTerminal );
|
||||
dlContact2->setFlags ( CntWeakTerminal );
|
||||
if (autoSource->getGCell() == doglegGCell)
|
||||
dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (isWeakTerminal()) {
|
||||
if (autoSource->getGCell() == doglegGCell) dlContact2->migrateConstraintBox( autoSource );
|
||||
} else if (isWeakTerminal()) {
|
||||
segment1->setFlags( SegWeakTerminal1 );
|
||||
segment2->setFlags( SegWeakTerminal1 );
|
||||
segment1->setRpDistance( getRpDistance() );
|
||||
segment2->setRpDistance( getRpDistance() );
|
||||
} else {
|
||||
segment1->setRpDistance( getRpDistance() );
|
||||
segment2->setRpDistance( getRpDistance() );
|
||||
}
|
||||
|
||||
// if (isSourceTerminal()) {
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegWeakTerminal1 );
|
||||
// autoTarget->unsetFlags( CntWeakTerminal );
|
||||
// dlContact1->setFlags ( CntWeakTerminal );
|
||||
// if (autoTarget->getGCell() == doglegGCell)
|
||||
// dlContact1->migrateConstraintBox( autoTarget );
|
||||
// } else if (isTargetTerminal()) {
|
||||
// unsetFlags( SegTargetTerminal );
|
||||
// setFlags( SegWeakTerminal1 );
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegTargetTerminal );
|
||||
// autoSource->unsetFlags( CntWeakTerminal );
|
||||
// dlContact2->setFlags ( CntWeakTerminal );
|
||||
// if (autoSource->getGCell() == doglegGCell)
|
||||
// dlContact2->migrateConstraintBox( autoSource );
|
||||
// } else if (isWeakTerminal()) {
|
||||
// segment1->setFlags( SegWeakTerminal1 );
|
||||
// segment2->setFlags( SegWeakTerminal1 );
|
||||
// }
|
||||
|
||||
if (isAnalog()) {
|
||||
segment1->setFlags( SegAnalog );
|
||||
segment2->setFlags( SegAnalog );
|
||||
|
@ -781,8 +816,11 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if ( isLocal()) autoSource->setFlags( AutoContactFlag::CntHDogleg );
|
||||
if (segment2->isLocal()) autoTarget->setFlags( AutoContactFlag::CntHDogleg );
|
||||
|
||||
if (autoTarget->canDrag() and not autoSource->canDrag()) {
|
||||
if (not autoTarget->getGCell()->isDevice()) {
|
||||
if (not autoTarget->getGCell()->isDevice() and (segment1->getGCell() == autoTarget->getGCell())) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
|
|
|
@ -478,8 +478,8 @@ namespace Anabatic {
|
|||
maxPos = bb.getXMax();
|
||||
|
||||
cdebug_log(112,0) << "Vertical gauge: " << gauge << endl;
|
||||
cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(ab.getXMin()) << endl;
|
||||
cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(ab.getXMax()) << endl;
|
||||
cdebug_log(112,0) << "ab.getXMin(): " << DbU::getValueString(bb.getXMin()) << endl;
|
||||
cdebug_log(112,0) << "ab.getXMax(): " << DbU::getValueString(bb.getXMax()) << endl;
|
||||
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl;
|
||||
} else {
|
||||
trackPos = gauge->getTrackPosition( ab.getYMin()
|
||||
|
@ -490,8 +490,8 @@ namespace Anabatic {
|
|||
maxPos = bb.getYMax();
|
||||
|
||||
cdebug_log(112,0) << "Horizontal gauge: " << gauge << endl;
|
||||
cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(ab.getYMin()) << endl;
|
||||
cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(ab.getYMax()) << endl;
|
||||
cdebug_log(112,0) << "ab.getYMin(): " << DbU::getValueString(bb.getYMin()) << endl;
|
||||
cdebug_log(112,0) << "ab.getYMax(): " << DbU::getValueString(bb.getYMax()) << endl;
|
||||
cdebug_log(112,0) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl;
|
||||
}
|
||||
|
||||
|
@ -501,7 +501,7 @@ namespace Anabatic {
|
|||
cdebug_log(112,0) << "| Nearest Pos: " << DbU::getValueString(trackPos) << endl;
|
||||
|
||||
if ( (trackPos >= minPos) and (trackPos <= maxPos) ) {
|
||||
if (not bestComponent or (bestSpan > maxPos-minPos)) {
|
||||
if (not bestComponent or (bestSpan < maxPos-minPos)) {
|
||||
bestComponent = component;
|
||||
bestSpan = maxPos - minPos;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace Anabatic {
|
|||
const BaseFlags Flags::ChannelRow = (1L << 13);
|
||||
const BaseFlags Flags::HRailGCell = (1L << 14);
|
||||
const BaseFlags Flags::VRailGCell = (1L << 15);
|
||||
const BaseFlags Flags::GoStraight = (1L << 16);
|
||||
// Flags for Edge objects states only.
|
||||
const BaseFlags Flags::NullCapacity = (1L << 5);
|
||||
const BaseFlags Flags::InfiniteCapacity = (1L << 6);
|
||||
|
@ -116,6 +117,7 @@ namespace Anabatic {
|
|||
const BaseFlags Flags::CheckLowUpDensity = (1L << 31);
|
||||
const BaseFlags Flags::NoUpdate = (1L << 32);
|
||||
const BaseFlags Flags::NorthPath = (1L << 33);
|
||||
const BaseFlags Flags::UseNonPref = (1L << 34);
|
||||
|
||||
|
||||
Flags::~Flags ()
|
||||
|
@ -169,6 +171,7 @@ namespace Anabatic {
|
|||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
string Flags::_getTypeName () const
|
||||
{ return "Anabatic::Flags"; }
|
||||
|
||||
|
|
|
@ -1535,6 +1535,7 @@ namespace Anabatic {
|
|||
|
||||
++_connectedsId;
|
||||
for ( Vertex* vertex : connecteds ) {
|
||||
vertex->getGCell()->flags().reset( Flags::GoStraight );
|
||||
vertex->setDistance ( Vertex::unreached );
|
||||
vertex->setStamp ( _stamp );
|
||||
vertex->setConnexId ( _connectedsId );
|
||||
|
|
|
@ -1215,7 +1215,7 @@ namespace Anabatic {
|
|||
int GCell::getCapacity ( size_t depth ) const
|
||||
{
|
||||
const vector<Edge*>* edges = NULL;
|
||||
if (isHorizontalPlane(depth)) edges = (_eastEdges .empty()) ? &_westEdges : &_westEdges;
|
||||
if (isHorizontalPlane(depth)) edges = (_eastEdges .empty()) ? &_westEdges : &_eastEdges;
|
||||
else edges = (_northEdges.empty()) ? &_southEdges : &_northEdges;
|
||||
|
||||
int capacity = 0;
|
||||
|
|
|
@ -31,11 +31,287 @@
|
|||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "anabatic/AutoContact.h"
|
||||
#include "anabatic/AutoContactTerminal.h"
|
||||
#include "anabatic/AutoSegment.h"
|
||||
#include "anabatic/AnabaticEngine.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace CRL;
|
||||
using namespace Hurricane;
|
||||
using namespace Anabatic;
|
||||
|
||||
|
||||
class SortRpByX {
|
||||
public:
|
||||
inline SortRpByX ();
|
||||
inline bool operator() ( RoutingPad* rp1, RoutingPad* rp2 );
|
||||
};
|
||||
|
||||
|
||||
inline SortRpByX::SortRpByX ()
|
||||
{ }
|
||||
|
||||
|
||||
inline bool SortRpByX::operator() ( RoutingPad* rp1, RoutingPad* rp2 )
|
||||
{
|
||||
DbU::Unit x1 = rp1->getCenter().getX();
|
||||
DbU::Unit x2 = rp2->getCenter().getX();
|
||||
|
||||
if (x1 == x2) return false;
|
||||
return (x1 < x2);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Class : "RpsInRow".
|
||||
|
||||
class RpsInRow {
|
||||
public:
|
||||
class Compare {
|
||||
public:
|
||||
bool operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const;
|
||||
};
|
||||
public:
|
||||
inline RpsInRow ( RoutingPad*, AnabaticEngine* );
|
||||
inline const vector<RoutingPad*>& getRps () const;
|
||||
inline size_t getSouth () const;
|
||||
inline size_t getNorth () const;
|
||||
inline const Interval& getRpsHSpan () const;
|
||||
inline const Interval& getRpsVSpan () const;
|
||||
void slacken ();
|
||||
private:
|
||||
void _findTopology ();
|
||||
inline void _merge ( RoutingPad* );
|
||||
private:
|
||||
AnabaticEngine* _anabatic;
|
||||
vector<RoutingPad*> _rps;
|
||||
size_t _north;
|
||||
size_t _south;
|
||||
Interval _hSpan;
|
||||
Interval _vSpan;
|
||||
};
|
||||
|
||||
|
||||
inline RpsInRow::RpsInRow ( RoutingPad* seed, AnabaticEngine* anabatic )
|
||||
: _anabatic(anabatic)
|
||||
, _rps ()
|
||||
, _north (0)
|
||||
, _south (0)
|
||||
, _hSpan ()
|
||||
, _vSpan ( false )
|
||||
{
|
||||
_rps.push_back( seed );
|
||||
_findTopology();
|
||||
}
|
||||
|
||||
|
||||
inline const vector<RoutingPad*>& RpsInRow::getRps () const { return _rps; }
|
||||
inline size_t RpsInRow::getSouth () const { return _south; }
|
||||
inline size_t RpsInRow::getNorth () const { return _north; }
|
||||
inline const Interval& RpsInRow::getRpsHSpan () const { return _hSpan; }
|
||||
inline const Interval& RpsInRow::getRpsVSpan () const { return _vSpan; }
|
||||
|
||||
|
||||
bool RpsInRow::Compare::operator() ( const RpsInRow* lhs, const RpsInRow* rhs ) const
|
||||
{
|
||||
if ( (lhs->_rps.size() == 2) and (rhs->_rps.size() != 2) ) return true;
|
||||
if ( (lhs->_rps.size() != 2) and (rhs->_rps.size() == 2) ) return false;
|
||||
if ( lhs->_rps.size() != rhs->_rps.size() ) return lhs->_rps.size() < rhs->_rps.size();
|
||||
|
||||
size_t lhsNs = lhs->_south + lhs->_north;
|
||||
size_t rhsNs = rhs->_south + rhs->_north;
|
||||
if (lhsNs != rhsNs) return lhsNs < rhsNs;
|
||||
|
||||
if (lhs->_vSpan != rhs->_vSpan) return lhs->_vSpan.getSize() < rhs->_vSpan.getSize();
|
||||
if (lhs->_hSpan != rhs->_hSpan) return lhs->_hSpan.getSize() < rhs->_hSpan.getSize();
|
||||
|
||||
return lhs->_rps[0]->getId() < rhs->_rps[0]->getId();
|
||||
}
|
||||
|
||||
|
||||
inline void RpsInRow::_merge ( RoutingPad* rp )
|
||||
{
|
||||
if (rp != _rps[0]) _rps.push_back( rp );
|
||||
|
||||
Box bb ( _rps.back()->getBoundingBox() );
|
||||
_hSpan.merge( bb.getCenter().getX() );
|
||||
_vSpan.intersection( bb.getYMin(), bb.getYMax() );
|
||||
}
|
||||
|
||||
|
||||
void RpsInRow::_findTopology ()
|
||||
{
|
||||
cdebug_log(146,1) << "RpsInRow::findTopology() - " << _rps[0] << endl;
|
||||
|
||||
_merge( _rps[0] );
|
||||
|
||||
AutoSegmentStack stack;
|
||||
|
||||
for ( Component* component : _rps[0]->getSlaveComponents() ) {
|
||||
cdebug_log(146,0) << "slave component: " << component << endl;
|
||||
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
|
||||
if (rpContact) {
|
||||
cdebug_log(146,0) << "Start rp: " << rpContact << endl;
|
||||
|
||||
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
|
||||
cdebug_log(146,0) << "Examining: " << segment << endl;
|
||||
AutoContact* target = segment->getOppositeAnchor(rpContact);
|
||||
|
||||
if (target) {
|
||||
if (segment->isHorizontal()) {
|
||||
stack.push( target, segment );
|
||||
} else {
|
||||
if (segment->isLocal()) {
|
||||
stack.push( target, segment );
|
||||
} else {
|
||||
if (segment->getAutoSource() == rpContact) ++_north;
|
||||
else ++_south;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find Rps in same horizontal GCell range.
|
||||
cdebug_log(146,0) << "Find Rps in same horizontal GCell range" << endl;
|
||||
|
||||
while ( not stack.isEmpty() ) {
|
||||
AutoSegment* from = stack.getAutoSegment();
|
||||
AutoContact* contact = stack.getAutoContact();
|
||||
stack.pop();
|
||||
|
||||
for ( AutoSegment* segment : contact->getAutoSegments() ) {
|
||||
if (segment == from) continue;
|
||||
if (segment->isVertical() and not segment->isLocal()) {
|
||||
if (segment->getAutoSource() == contact) ++_north;
|
||||
else ++_south;
|
||||
continue;
|
||||
}
|
||||
|
||||
AutoContact* target = segment->getOppositeAnchor( contact );
|
||||
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( target );
|
||||
if (terminal) {
|
||||
_merge( terminal->getRoutingPad() );
|
||||
}
|
||||
|
||||
stack.push( target, segment );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort( _rps.begin(), _rps.end(), SortRpByX() );
|
||||
|
||||
cdebug_log(146,0) << "findHAlignedsRps() - Exit" << endl;
|
||||
cdebug_tabw(146,-1);
|
||||
}
|
||||
|
||||
|
||||
void RpsInRow::slacken ()
|
||||
{
|
||||
cdebug_log(149,1) << "RpsInRow::slacken()" << endl;
|
||||
|
||||
for ( RoutingPad* rp : _rps ) {
|
||||
cdebug_log(149,0) << "Slacken from: " << rp << endl;
|
||||
|
||||
if (rp->getLayer()) {
|
||||
if (_anabatic->getConfiguration()->getLayerDepth(rp->getLayer()) == 1)
|
||||
cdebug_log(149,0) << "In METAL2, skiping" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( Component* component : rp->getSlaveComponents() ) {
|
||||
AutoContact* rpContact = Session::lookup( dynamic_cast<Contact*>(component) );
|
||||
if (rpContact) {
|
||||
cdebug_log(149,0) << "+ " << rpContact << endl;
|
||||
for ( AutoSegment* segment : rpContact->getAutoSegments() ) {
|
||||
cdebug_log(149,0) << "| " << segment << endl;
|
||||
|
||||
if (segment->isVertical()) {
|
||||
if (segment->getDepth() == 1) {
|
||||
cdebug_log(149,0) << "| Slacken: " << segment << endl;
|
||||
segment->changeDepth( 2, Flags::NoFlags );
|
||||
cdebug_log(149,0) << "| After Slacken: " << segment << endl;
|
||||
}
|
||||
} else {
|
||||
segment->makeDogleg( rpContact->getGCell() );
|
||||
cdebug_log(149,0) << "| Make dogleg: " << segment << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cdebug_tabw(149,-1);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Class : "GCellRps".
|
||||
|
||||
class GCellRps {
|
||||
public:
|
||||
class Compare {
|
||||
public:
|
||||
bool operator() ( const GCellRps* lhs, const GCellRps* rhs ) const;
|
||||
};
|
||||
public:
|
||||
GCellRps ( GCell*, AnabaticEngine* );
|
||||
~GCellRps ();
|
||||
inline GCell* getGCell () const;
|
||||
inline size_t add ( RoutingPad* );
|
||||
inline void consolidate ();
|
||||
inline RpsInRow* getRpsInRow ( size_t i );
|
||||
inline const vector<RpsInRow*>& getRpsInRows () const;
|
||||
private:
|
||||
AnabaticEngine* _anabatic;
|
||||
GCell* _gcell;
|
||||
vector<RpsInRow*> _rpsInRows;
|
||||
};
|
||||
|
||||
|
||||
GCellRps::GCellRps ( GCell* gcell, AnabaticEngine* anabatic )
|
||||
: _anabatic (anabatic)
|
||||
, _gcell (gcell)
|
||||
, _rpsInRows()
|
||||
{ }
|
||||
|
||||
|
||||
GCellRps::~GCellRps ()
|
||||
{
|
||||
for ( RpsInRow* elem : _rpsInRows ) delete elem;
|
||||
}
|
||||
|
||||
|
||||
inline GCell* GCellRps::getGCell () const { return _gcell; }
|
||||
|
||||
|
||||
inline size_t GCellRps::add ( RoutingPad* rp )
|
||||
{
|
||||
_rpsInRows.push_back( new RpsInRow(rp,_anabatic) );
|
||||
return _rpsInRows.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
inline void GCellRps::consolidate ()
|
||||
{
|
||||
sort( _rpsInRows.begin(), _rpsInRows.end(), RpsInRow::Compare() );
|
||||
}
|
||||
|
||||
|
||||
inline RpsInRow* GCellRps::getRpsInRow ( size_t i ) { return _rpsInRows[i]; }
|
||||
inline const vector<RpsInRow*>& GCellRps::getRpsInRows () const { return _rpsInRows; }
|
||||
|
||||
|
||||
bool GCellRps::Compare::operator() ( const GCellRps* lhs, const GCellRps* rhs ) const
|
||||
{ return lhs->getGCell()->getId() < rhs->getGCell()->getId(); }
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace Anabatic {
|
||||
|
||||
using Hurricane::DebugSession;
|
||||
|
@ -645,6 +921,54 @@ namespace Anabatic {
|
|||
|
||||
Session::setAnabaticFlags( Flags::WarnOnGCellOverload );
|
||||
}
|
||||
|
||||
set<GCellRps*,GCellRps::Compare> gcellRpss;
|
||||
|
||||
for ( GCell* gcell : getGCells() ) {
|
||||
set<RoutingPad*,Entity::CompareById> rps;
|
||||
|
||||
const vector<AutoContact*> contacts = gcell->getContacts();
|
||||
for ( AutoContact* contact : contacts ) {
|
||||
AutoContactTerminal* terminal = dynamic_cast<AutoContactTerminal*>( contact );
|
||||
if (terminal) {
|
||||
rps.insert( terminal->getRoutingPad() );
|
||||
}
|
||||
}
|
||||
if (rps.size() > 8) {
|
||||
GCellRps* gcellRps = new GCellRps ( gcell, this );
|
||||
gcellRpss.insert( gcellRps );
|
||||
|
||||
for ( RoutingPad* rp : rps ) gcellRps->add( rp );
|
||||
}
|
||||
}
|
||||
|
||||
for ( GCellRps* gcellRps : gcellRpss ) {
|
||||
gcellRps->consolidate();
|
||||
|
||||
const vector<RpsInRow*>& rpsInRows = gcellRps->getRpsInRows();
|
||||
cdebug_log(149,0) << gcellRps->getGCell() << " has " << rpsInRows.size() << " terminals." << endl;
|
||||
|
||||
size_t count = 0;
|
||||
for ( RpsInRow* rpsInRow : rpsInRows ) {
|
||||
cdebug_log(149,0) << "North:" << rpsInRow->getNorth() << " South:"
|
||||
<< rpsInRow->getSouth() << " net:"
|
||||
<< rpsInRow->getRps()[0]->getNet()->getName() << endl;
|
||||
cdebug_log(149,0) << "H-Span:" << rpsInRow->getRpsHSpan() << " V-Span:" << rpsInRow->getRpsVSpan() << endl;
|
||||
for ( RoutingPad* arp : rpsInRow->getRps() ) {
|
||||
cdebug_log(149,0) << "| " << arp << endl;
|
||||
}
|
||||
if (++count < 2) rpsInRow->slacken();
|
||||
}
|
||||
|
||||
for ( AutoSegment* segment : gcellRps->getGCell()->getHSegments() ) {
|
||||
if (segment->canPivotUp()) {
|
||||
cdebug_log(149,0) << "Move up horizontal: " << segment << endl;
|
||||
segment->moveUp( Flags::Propagate );
|
||||
}
|
||||
}
|
||||
|
||||
delete gcellRps;
|
||||
}
|
||||
|
||||
checkGCellDensities();
|
||||
Session::close();
|
||||
|
|
|
@ -165,27 +165,81 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::doRp_Access() - flags:" << flags << endl;
|
||||
|
||||
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
|
||||
AutoContact* rpSourceContact;
|
||||
AutoContact* rpContactTarget;
|
||||
|
||||
Flags useNonPref = Flags::NoFlags;
|
||||
if (flags & UseNonPref) useNonPref |= Flags::UseNonPref;
|
||||
|
||||
flags |= checkRoutingPadSize( rp );
|
||||
|
||||
doRp_AutoContacts( gcell, rp, rpSourceContact, rpContactTarget, flags );
|
||||
|
||||
if (flags & HAccess) {
|
||||
if (flags & VSmall) {
|
||||
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
|
||||
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
|
||||
rpSourceContact = subContact2;
|
||||
cdebug_log(145,0) << "flags: " << flags << endl;
|
||||
if ((rpDepth == 0) or (rpDepth == 2)) {
|
||||
cdebug_log(145,0) << "case: METAL1 or METAL3 RoutingPad." << endl;
|
||||
|
||||
if (flags & HAccess) {
|
||||
cdebug_log(145,0) << "case: HAccess" << endl;
|
||||
|
||||
if ( ((flags & VSmall) and not ((flags & UseNonPref)) or (flags & Punctual)) ) {
|
||||
cdebug_log(145,0) << "case: VSmall and *not* UseNonPref" << endl;
|
||||
|
||||
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
|
||||
rpSourceContact = subContact1;
|
||||
|
||||
flags &= ~UseNonPref;
|
||||
useNonPref.reset( Flags::UseNonPref );
|
||||
}
|
||||
|
||||
if (flags & (VSmall|UseNonPref)) {
|
||||
cdebug_log(145,0) << "case: UseNonPref" << endl;
|
||||
|
||||
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical|useNonPref );
|
||||
rpSourceContact = subContact1;
|
||||
}
|
||||
} else {
|
||||
if (flags & HSmall) {
|
||||
cdebug_log(145,0) << "case: HSmall" << endl;
|
||||
|
||||
AutoContact* subContact1 = rpSourceContact;
|
||||
AutoContact* subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
|
||||
rpSourceContact = subContact2;
|
||||
|
||||
if (flags & Punctual) {
|
||||
cdebug_log(145,0) << "case: HSmall + Punctual" << endl;
|
||||
subContact1 = subContact2;
|
||||
subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( subContact1, subContact2, Flags::Vertical );
|
||||
|
||||
subContact1 = subContact2;
|
||||
subContact2 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( subContact1, subContact2, Flags::Horizontal );
|
||||
|
||||
rpSourceContact = subContact2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (flags & HSmall) {
|
||||
AutoContact* subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
cdebug_log(145,0) << "case: METAL2." << endl;
|
||||
AutoContact* subContact1 = NULL;
|
||||
|
||||
if (flags & HAccess) {
|
||||
if (flags & HAccessEW)
|
||||
subContact1 = AutoContactHTee::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
else
|
||||
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
|
||||
AutoSegment::create( rpSourceContact, subContact1, Flags::Vertical );
|
||||
} else {
|
||||
subContact1 = AutoContactTurn::create( gcell, rp->getNet(), Session::getContactLayer(1) );
|
||||
AutoSegment::create( rpSourceContact, subContact1, Flags::Horizontal );
|
||||
rpSourceContact = subContact1;
|
||||
}
|
||||
rpSourceContact = subContact1;
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
|
@ -198,6 +252,7 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(145,1) << getTypeName() << "::_do_1G_1M1() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||
|
||||
#if THIS_IS_DISABLED
|
||||
uint64_t flags = NoFlags;
|
||||
if (east() ) { flags |= HAccess; }
|
||||
else if (west() ) { flags |= HAccess; }
|
||||
|
@ -205,8 +260,16 @@ namespace Anabatic {
|
|||
else if (south()) { flags |= VSmall; }
|
||||
|
||||
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],flags) );
|
||||
#endif
|
||||
|
||||
if (north() or south()) {
|
||||
setBothCornerContacts( doRp_Access(getGCell(),getRoutingPads()[0],VSmall) );
|
||||
} else {
|
||||
setBothCornerContacts( doRp_Access( getGCell(), getRoutingPads()[0], UseNonPref|HAccess ) );
|
||||
}
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -217,8 +280,8 @@ namespace Anabatic {
|
|||
|
||||
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
|
||||
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
|
||||
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess );
|
||||
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess );
|
||||
AutoContact* leftContact = doRp_Access( getGCell(), getRoutingPads()[i-1], HAccess|UseNonPref );
|
||||
AutoContact* rightContact = doRp_Access( getGCell(), getRoutingPads()[i ], HAccess|UseNonPref );
|
||||
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
|
||||
}
|
||||
|
||||
|
@ -606,8 +669,7 @@ namespace Anabatic {
|
|||
|
||||
cdebug_log(145,1) << getTypeName()
|
||||
<< "::_do_xG_" << (int)getConnexity().fields.M1
|
||||
<< "M1_" << (int)getConnexity().fields.M3
|
||||
<< "M3() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
|
||||
<< "M1() [G:" << (int)getConnexity().fields.globals << " Managed Configuration]" << endl;
|
||||
cdebug_log(145,0) << "getConnexity(): " << getConnexity().connexity << endl;
|
||||
cdebug_log(145,0) << "north: " << north() << endl;
|
||||
cdebug_log(145,0) << "south: " << south() << endl;
|
||||
|
@ -623,23 +685,43 @@ namespace Anabatic {
|
|||
AutoSegment::create( contact1, contact2, Flags::Horizontal );
|
||||
setBothCornerContacts( contact2 );
|
||||
} else if (east() and west()) {
|
||||
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
|
||||
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact1, contact2, Flags::Vertical );
|
||||
setBothCornerContacts( contact2 );
|
||||
// AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags );
|
||||
// AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
// AutoSegment::create( contact1, contact2, Flags::Vertical );
|
||||
// setBothCornerContacts( contact2 );
|
||||
AutoContact* contact1 = NULL;
|
||||
AutoContact* contact2 = NULL;
|
||||
uint64_t flags = checkRoutingPadSize( getRoutingPads()[0] );
|
||||
|
||||
if (flags & VSmall) {
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
|
||||
contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact1, contact2, Flags::Vertical );
|
||||
|
||||
setBothCornerContacts( contact2 );
|
||||
} else {
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
|
||||
setSouthWestContact( contact1 );
|
||||
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[0], contact1, contact2, NoFlags );
|
||||
setNorthEastContact( contact1 );
|
||||
}
|
||||
} else {
|
||||
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
|
||||
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoContact* contact2 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact1, contact2, Flags::Horizontal );
|
||||
setBothCornerContacts( contact2 );
|
||||
|
||||
contact1 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact1, contact2, Flags::Vertical );
|
||||
setBothCornerContacts( contact1 );
|
||||
}
|
||||
} else if (getConnexity().fields.globals == 3) {
|
||||
if (not west() or not east()) {
|
||||
AutoContact* contact1 = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
|
||||
AutoContact* contact2 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoContact* contact2 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact1, contact2, Flags::Horizontal );
|
||||
AutoContact* contact3 = AutoContactHTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact2, contact3, Flags::Horizontal );
|
||||
AutoContact* contact3 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( contact2, contact3, Flags::Vertical );
|
||||
|
||||
setSouthWestContact( (east()) ? contact2 : contact3 );
|
||||
setNorthEastContact( (east()) ? contact3 : contact2 );
|
||||
|
@ -763,18 +845,18 @@ namespace Anabatic {
|
|||
rpM3 = getRoutingPads()[i];
|
||||
}
|
||||
|
||||
const Layer* viaLayer1 = Session::getContactLayer(1);
|
||||
AutoContact* unusedContact = NULL;
|
||||
const Layer* viaLayer1 = Session::getContactLayer(1);
|
||||
AutoContact* subContact1 = NULL;
|
||||
|
||||
if (rpM3) {
|
||||
// At least one M3 RoutingPad is present: use it.
|
||||
if (west() and not south()) {
|
||||
setSouthWestContact( doRp_Access( getGCell(), getRoutingPads()[0], HAccess ) );
|
||||
} else if (not west() and south()) {
|
||||
doRp_AutoContacts( getGCell(), rpM3, getSouthWestContact(), unusedContact, DoSourceContact );
|
||||
doRp_AutoContacts( getGCell(), rpM3, getSouthWestContact(), subContact1, DoSourceContact );
|
||||
} else if (west() and south()) {
|
||||
AutoContact* rpContact = NULL;
|
||||
doRp_AutoContacts( getGCell(), rpM3, rpContact, unusedContact, DoSourceContact );
|
||||
doRp_AutoContacts( getGCell(), rpM3, rpContact, subContact1, DoSourceContact );
|
||||
setSouthWestContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
|
||||
AutoSegment::create( rpContact, getSouthWestContact(), Flags::Vertical );
|
||||
}
|
||||
|
@ -782,24 +864,46 @@ namespace Anabatic {
|
|||
if (east() and not north()) {
|
||||
setNorthEastContact( doRp_Access( getGCell(), getRoutingPads()[getRoutingPads().size()-1], HAccess ) );
|
||||
} else if (not east() and north()) {
|
||||
doRp_AutoContacts( getGCell(), rpM3, unusedContact, getNorthEastContact(), DoTargetContact );
|
||||
doRp_AutoContacts( getGCell(), rpM3, subContact1, getNorthEastContact(), DoTargetContact );
|
||||
} else if (east() and north()) {
|
||||
AutoContact* rpContact = NULL;
|
||||
doRp_AutoContacts( getGCell(), rpM3, unusedContact, rpContact, DoTargetContact );
|
||||
doRp_AutoContacts( getGCell(), rpM3, subContact1, rpContact, DoTargetContact );
|
||||
setNorthEastContact( AutoContactVTee::create( getGCell(), getNet(), viaLayer1 ) );
|
||||
AutoSegment::create( rpContact, getNorthEastContact(), Flags::Vertical );
|
||||
}
|
||||
} else {
|
||||
cdebug_log(145,0) << "getRoutingPads().size():" << getRoutingPads().size()<< endl;
|
||||
|
||||
if (getRoutingPads().size() == 1) {
|
||||
if ( ((east () != NULL) xor (west () != NULL))
|
||||
and ((north() != NULL) xor (south() != NULL)) ) {
|
||||
cdebug_log(145,0) << "case: One M1, with global turn." << endl;
|
||||
|
||||
AutoContact* rpContact = doRp_Access( getGCell(), getRoutingPads()[0], HAccess );
|
||||
subContact1 = AutoContactTurn::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( rpContact, subContact1, Flags::Horizontal );
|
||||
|
||||
rpContact = subContact1;
|
||||
subContact1 = AutoContactVTee::create( getGCell(), getNet(), viaLayer1 );
|
||||
AutoSegment::create( rpContact, subContact1, Flags::Vertical );
|
||||
|
||||
setBothCornerContacts( subContact1 );
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// All RoutingPad are M1.
|
||||
Component* southWestRp = getRoutingPads()[0];
|
||||
cdebug_log(145,0) << "| Initial S-W Global RP: " << southWestRp << endl;
|
||||
for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
|
||||
if (southWestRp->getBoundingBox().getHeight() >= 4*Session::getPitch(1)) break;
|
||||
if (getRoutingPads()[i]->getBoundingBox().getHeight() > southWestRp->getBoundingBox().getHeight()) {
|
||||
cdebug_log(145,0) << "| Better RP: " << southWestRp << endl;
|
||||
southWestRp = getRoutingPads()[i];
|
||||
}
|
||||
}
|
||||
// for ( size_t i=1 ; i<getRoutingPads().size() ; ++i ) {
|
||||
// if (southWestRp->getBoundingBox().getHeight() >= 4*Session::getPitch(1)) break;
|
||||
// if (getRoutingPads()[i]->getBoundingBox().getHeight() > southWestRp->getBoundingBox().getHeight()) {
|
||||
// southWestRp = getRoutingPads()[i];
|
||||
// cdebug_log(145,0) << "| Better RP: " << southWestRp << endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (west() and not south()) {
|
||||
setSouthWestContact( doRp_Access( getGCell(), southWestRp, HAccess ) );
|
||||
|
@ -883,11 +987,17 @@ namespace Anabatic {
|
|||
biggestRp = getRoutingPads()[i];
|
||||
}
|
||||
|
||||
const Layer* viaLayer1 = Session::getContactLayer(1);
|
||||
AutoContact* unusedContact = NULL;
|
||||
const Layer* viaLayer1 = Session::getContactLayer(1);
|
||||
|
||||
if (east() and west() and not south() and not north()) {
|
||||
AutoContact* rpContact = doRp_Access( getGCell(), biggestRp, HBothAccess );
|
||||
setBothCornerContacts( rpContact );
|
||||
cdebug_tabw(145,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (west() and not south()) {
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[0], getSouthWestContact(), unusedContact, DoSourceContact );
|
||||
setSouthWestContact( doRp_Access( getGCell(), getRoutingPads()[0], HAccess ) );
|
||||
} else if (not west() and south()) {
|
||||
setSouthWestContact( doRp_Access( getGCell(), biggestRp, NoFlags ) );
|
||||
} else if (west() and south()) {
|
||||
|
@ -897,7 +1007,7 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
if (east() and not north()) {
|
||||
doRp_AutoContacts( getGCell(), getRoutingPads()[getRoutingPads().size()-1], getNorthEastContact(), unusedContact, DoSourceContact );
|
||||
setNorthEastContact( doRp_Access( getGCell(), getRoutingPads()[getRoutingPads().size()-1], HAccess ) );
|
||||
} else if (not east() and north()) {
|
||||
setNorthEastContact( doRp_Access( getGCell(), biggestRp, NoFlags ) );
|
||||
} else if (east() and north()) {
|
||||
|
|
|
@ -61,55 +61,55 @@ namespace {
|
|||
|
||||
void propagateConstraintFromRp ( RoutingPad* rp )
|
||||
{
|
||||
cdebug_log(145,1) << "propagateConstraintFromRp() - " << rp << endl;
|
||||
cdebug_log(146,1) << "propagateConstraintFromRp() - " << rp << endl;
|
||||
|
||||
for ( Component* component : rp->getSlaveComponents() ) {
|
||||
cdebug_log(145,0) << "slave component: " << component << endl;
|
||||
cdebug_log(146,0) << "slave component: " << component << endl;
|
||||
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
|
||||
if (sourceContact) {
|
||||
Box constraintBox = sourceContact->getConstraintBox();
|
||||
|
||||
cdebug_log(145,0) << "Start slave: " << sourceContact << endl;
|
||||
cdebug_log(145,0) << "Constraint: " << constraintBox << endl;
|
||||
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
|
||||
cdebug_log(146,0) << "Constraint: " << constraintBox << endl;
|
||||
|
||||
set<AutoSegment*> verticalSegments;
|
||||
set<AutoSegment*> horizontalSegments;
|
||||
|
||||
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
|
||||
cdebug_log(145,0) << "Examining: " << segment << endl;
|
||||
cdebug_log(146,0) << "Examining: " << segment << endl;
|
||||
AutoContact* targetContact = segment->getOppositeAnchor(sourceContact);
|
||||
|
||||
if (targetContact) {
|
||||
if (segment->isHorizontal()) {
|
||||
cdebug_log(145,0) << "On horizontal stack " << segment << endl;
|
||||
cdebug_log(146,0) << "On horizontal stack " << segment << endl;
|
||||
horizontalSegments.insert( segment );
|
||||
} else {
|
||||
cdebug_log(145,0) << "On vertical stack " << segment << endl;
|
||||
cdebug_log(146,0) << "On vertical stack " << segment << endl;
|
||||
verticalSegments.insert( segment );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate constraint through horizontally aligned segments.
|
||||
cdebug_log(145,0) << "Propagate constraint on horizontal segments" << endl;
|
||||
cdebug_log(146,0) << "Propagate constraint on horizontal segments" << endl;
|
||||
|
||||
for ( AutoSegment* horizontal : horizontalSegments ) {
|
||||
AutoContact* contact = NULL;
|
||||
for ( AutoSegment* aligned : horizontal->getAligneds(Flags::WithSelf) ) {
|
||||
cdebug_log(145,0) << "aligned horizontal: " << aligned << endl;
|
||||
cdebug_log(146,0) << "aligned horizontal: " << aligned << endl;
|
||||
|
||||
contact = aligned->getAutoTarget();
|
||||
cdebug_log(145,0) << "contact: " << contact << endl;
|
||||
cdebug_log(146,0) << "contact: " << contact << endl;
|
||||
if (contact) {
|
||||
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
|
||||
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
|
||||
contact->restrictConstraintBox( constraintBox.getYMin()
|
||||
, constraintBox.getYMax()
|
||||
, Flags::Horizontal|Flags::WarnOnError );
|
||||
}
|
||||
contact = aligned->getAutoSource();
|
||||
cdebug_log(145,0) << "contact: " << contact << endl;
|
||||
cdebug_log(146,0) << "contact: " << contact << endl;
|
||||
if (contact) {
|
||||
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
|
||||
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
|
||||
contact->restrictConstraintBox( constraintBox.getYMin()
|
||||
, constraintBox.getYMax()
|
||||
, Flags::Horizontal|Flags::WarnOnError );
|
||||
|
@ -118,23 +118,23 @@ namespace {
|
|||
}
|
||||
|
||||
// Propagate constraint through vertically aligned segments.
|
||||
cdebug_log(145,0) << "Propagate constraint on vertical segments" << endl;
|
||||
cdebug_log(146,0) << "Propagate constraint on vertical segments" << endl;
|
||||
|
||||
for ( AutoSegment* vertical : verticalSegments ) {
|
||||
AutoContact* contact = NULL;
|
||||
for ( AutoSegment* aligned : vertical->getAligneds(Flags::WithSelf) ) {
|
||||
cdebug_log(145,0) << "aligned vertical: " << aligned << endl;
|
||||
cdebug_log(146,0) << "aligned vertical: " << aligned << endl;
|
||||
|
||||
contact = aligned->getAutoTarget();
|
||||
if (contact) {
|
||||
cdebug_log(145,0) << "Apply to (target): " << contact << endl;
|
||||
cdebug_log(146,0) << "Apply to (target): " << contact << endl;
|
||||
contact->restrictConstraintBox( constraintBox.getXMin()
|
||||
, constraintBox.getXMax()
|
||||
, Flags::Vertical|Flags::WarnOnError );
|
||||
}
|
||||
contact = aligned->getAutoSource();
|
||||
if (contact) {
|
||||
cdebug_log(145,0) << "Apply to (source): " << contact << endl;
|
||||
cdebug_log(146,0) << "Apply to (source): " << contact << endl;
|
||||
contact->restrictConstraintBox( constraintBox.getXMin()
|
||||
, constraintBox.getXMax()
|
||||
, Flags::Vertical|Flags::WarnOnError );
|
||||
|
@ -144,8 +144,8 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
cdebug_log(145,0) << "propagateConstraintFromRp() - Exit" << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
cdebug_log(146,0) << "propagateConstraintFromRp() - Exit" << endl;
|
||||
cdebug_tabw(146,-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,12 +159,78 @@ namespace Anabatic {
|
|||
using Hurricane::Cell;
|
||||
|
||||
|
||||
void propagateDistanceFromRp ( RoutingPad* rp )
|
||||
{
|
||||
cdebug_log(146,1) << "propagateDistanceFromRp() - " << rp << endl;
|
||||
|
||||
unsigned int distance = 0;
|
||||
vector< pair<AutoContact*,AutoSegment*> > currents;
|
||||
vector< pair<AutoContact*,AutoSegment*> > successors;
|
||||
|
||||
for ( Component* component : rp->getSlaveComponents() ) {
|
||||
cdebug_log(146,0) << "slave component: " << component << endl;
|
||||
|
||||
AutoContact* sourceContact = Session::lookup( dynamic_cast<Contact*>(component) );
|
||||
if (sourceContact) {
|
||||
cdebug_log(146,0) << "Start slave: " << sourceContact << endl;
|
||||
|
||||
for ( AutoSegment* segment : sourceContact->getAutoSegments() ) {
|
||||
cdebug_log(146,0) << "Pushing: " << segment << endl;
|
||||
currents.push_back( make_pair(sourceContact,segment) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ( not currents.empty() ) {
|
||||
for ( size_t i = 0 ; i<currents.size() ; ++i ) {
|
||||
AutoContact* source = currents[i].first;
|
||||
AutoSegment* segment = currents[i].second;
|
||||
|
||||
if ( (distance == 1) and (segment->getRpDistance() == 1) ) {
|
||||
vector<GCell*> gcells;
|
||||
segment->getGCells( gcells );
|
||||
|
||||
if (gcells.size() < 3)
|
||||
segment->setFlags( AutoSegment::SegUnbreakable );
|
||||
}
|
||||
|
||||
if (distance >= segment->getRpDistance()) continue;
|
||||
segment->setRpDistance( distance );
|
||||
cdebug_log(146,0) << "Popped: " << segment << endl;
|
||||
|
||||
AutoContact* target = segment->getOppositeAnchor( source );
|
||||
if (target) {
|
||||
for ( AutoSegment* successor : target->getAutoSegments() ) {
|
||||
if (successor == segment) continue;
|
||||
|
||||
// if (successor->isNonPref()) {
|
||||
// cdebug_log(146,0) << "Pushing (non-pref): " << successor << endl;
|
||||
// currents.push_back( make_pair(target,successor) );
|
||||
// } else {
|
||||
cdebug_log(146,0) << "Pushing: " << successor << endl;
|
||||
successors.push_back( make_pair(target,successor) );
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (++distance > 15) break;
|
||||
|
||||
currents.clear();
|
||||
currents.swap( successors );
|
||||
}
|
||||
|
||||
cdebug_log(146,0) << "propagateDistanceFromRp() - Exit" << endl;
|
||||
cdebug_tabw(146,-1);
|
||||
}
|
||||
|
||||
|
||||
void AnabaticEngine::computeNetConstraints ( Net* net )
|
||||
{
|
||||
DebugSession::open( net, 145, 150);
|
||||
DebugSession::open( net, 146, 150);
|
||||
|
||||
cdebug_log(149,0) << "Anabatic::computeNetConstraints( " << net << " )" << endl;
|
||||
cdebug_tabw(145,1);
|
||||
cdebug_tabw(146,1);
|
||||
|
||||
vector<RoutingPad*> routingPads;
|
||||
forEach ( Component*, icomponent, net->getComponents() ) {
|
||||
|
@ -179,15 +245,35 @@ namespace Anabatic {
|
|||
}
|
||||
}
|
||||
|
||||
for ( size_t i=0 ; i<routingPads.size() ; i++ )
|
||||
for ( size_t i=0 ; i<routingPads.size() ; i++ ) {
|
||||
propagateConstraintFromRp( routingPads[i] );
|
||||
propagateDistanceFromRp ( routingPads[i] );
|
||||
}
|
||||
|
||||
for ( Segment* segment : net->getSegments() ) {
|
||||
AutoSegment* autoSegment = Session::lookup( segment );
|
||||
if (not autoSegment) continue;
|
||||
if (autoSegment->isUnbreakable()) continue;
|
||||
if (autoSegment->getRpDistance() >= 2) continue;
|
||||
if (autoSegment->getRpDistance() == 1) continue;
|
||||
|
||||
vector<GCell*> gcells;
|
||||
autoSegment->getGCells( gcells );
|
||||
|
||||
if (gcells.size() > 2) continue;
|
||||
//if ( (gcells.size() == 2)
|
||||
// and ( not autoSegment->getAutoSource()->isTerminal()
|
||||
// or not autoSegment->getAutoTarget()->isTerminal()) ) continue;
|
||||
|
||||
autoSegment->setFlags( AutoSegment::SegUnbreakable );
|
||||
}
|
||||
|
||||
// forEach ( Segment*, isegment, net->getSegments() ) {
|
||||
// AutoSegment* autoSegment = Session::lookup( *isegment );
|
||||
// if (autoSegment) autoSegment->toConstraintAxis();
|
||||
// }
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
cdebug_tabw(146,-1);
|
||||
DebugSession::close();
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ namespace Anabatic {
|
|||
_anabatic->updateNetTopology ( net );
|
||||
_anabatic->computeNetConstraints( net );
|
||||
_anabatic->_computeNetOptimals ( net );
|
||||
_anabatic->_computeNetTerminals ( net );
|
||||
//_anabatic->_computeNetTerminals ( net );
|
||||
}
|
||||
_canonize ();
|
||||
|
||||
|
|
|
@ -161,7 +161,12 @@ namespace Anabatic {
|
|||
inline bool operator() ( const NetData* lhs, const NetData* rhs ) const
|
||||
{
|
||||
if (lhs->isMixedPreRoute() != rhs->isMixedPreRoute()) return lhs->isMixedPreRoute();
|
||||
if (lhs->getSparsity() != rhs->getSparsity() ) return lhs->getSparsity() < rhs->getSparsity();
|
||||
if ((lhs->getRpCount() > 10) or (rhs->getRpCount() > 10)) {
|
||||
if (lhs->getRpCount() != rhs->getRpCount())
|
||||
return lhs->getRpCount() > rhs->getRpCount();
|
||||
}
|
||||
|
||||
if (lhs->getSparsity() != rhs->getSparsity()) return lhs->getSparsity() < rhs->getSparsity();
|
||||
return lhs->getNet()->getId() < rhs->getNet()->getId();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace Anabatic {
|
|||
, CntOnVertical = (1 << 14)
|
||||
, CntOnHorizontal = (1 << 15)
|
||||
, CntDrag = (1 << 16)
|
||||
, CntHDogleg = (1 << 17)
|
||||
, CntVDogleg = (1 << 18)
|
||||
};
|
||||
|
||||
class AutoContact {
|
||||
|
@ -119,6 +121,8 @@ namespace Anabatic {
|
|||
inline bool isVTee () const;
|
||||
inline bool isFixed () const;
|
||||
inline bool isUserNativeConstraints () const;
|
||||
inline bool isHDogleg () const;
|
||||
inline bool isVDogleg () const;
|
||||
inline bool hasBadTopology () const;
|
||||
bool canDestroy ( Flags flags=Flags::NoFlags ) const;
|
||||
bool canMoveUp ( const AutoSegment* moved ) const;
|
||||
|
@ -259,6 +263,8 @@ namespace Anabatic {
|
|||
inline bool AutoContact::isTerminal () const { return _flags&CntTerminal; }
|
||||
inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
|
||||
inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
|
||||
inline bool AutoContact::isHDogleg () const { return _flags&CntHDogleg; }
|
||||
inline bool AutoContact::isVDogleg () const { return _flags&CntVDogleg; }
|
||||
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
|
||||
inline bool AutoContact::canDrag () const { return _flags&CntDrag; }
|
||||
inline size_t AutoContact::getId () const { return _id; }
|
||||
|
|
|
@ -58,11 +58,10 @@ namespace Anabatic {
|
|||
class AutoHorizontal;
|
||||
class AutoVertical;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "AutoSegment".
|
||||
|
||||
|
||||
|
||||
class AutoSegment {
|
||||
friend class AutoHorizontal;
|
||||
friend class AutoVertical;
|
||||
|
@ -106,6 +105,8 @@ namespace Anabatic {
|
|||
static const uint64_t SegAnalog = (1L<<33);
|
||||
static const uint64_t SegWide = (1L<<34);
|
||||
static const uint64_t SegShortNet = (1L<<35);
|
||||
static const uint64_t SegUnbreakable = (1L<<36);
|
||||
static const uint64_t SegNonPref = (1L<<37);
|
||||
// Masks.
|
||||
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
|
||||
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
|
||||
|
@ -194,6 +195,8 @@ namespace Anabatic {
|
|||
inline bool isWeakTerminal1 () const;
|
||||
inline bool isWeakTerminal2 () const;
|
||||
inline bool isTerminal () const;
|
||||
inline bool isUnbreakable () const;
|
||||
inline bool isNonPref () const;
|
||||
inline bool isDrag () const;
|
||||
inline bool isNotSourceAligned () const;
|
||||
inline bool isNotTargetAligned () const;
|
||||
|
@ -245,6 +248,7 @@ namespace Anabatic {
|
|||
AutoContact* getOppositeAnchor ( AutoContact* ) const;
|
||||
size_t getPerpandicularsBound ( set<AutoSegment*>& );
|
||||
inline AutoSegment* getParent () const;
|
||||
inline unsigned int getRpDistance () const;
|
||||
inline unsigned int getDepth () const;
|
||||
inline DbU::Unit getPitch () const;
|
||||
DbU::Unit getPPitch () const;
|
||||
|
@ -282,6 +286,7 @@ namespace Anabatic {
|
|||
inline void unsetFlags ( uint64_t );
|
||||
inline void setFlags ( uint64_t );
|
||||
void setFlagsOnAligneds ( uint64_t );
|
||||
inline void setRpDistance ( unsigned int );
|
||||
inline void incReduceds ();
|
||||
inline void decReduceds ();
|
||||
virtual void setDuSource ( DbU::Unit du ) = 0;
|
||||
|
@ -370,10 +375,11 @@ namespace Anabatic {
|
|||
const unsigned long _id;
|
||||
GCell* _gcell;
|
||||
uint64_t _flags;
|
||||
unsigned int _depth : 8;
|
||||
unsigned int _optimalMin :16;
|
||||
unsigned int _optimalMax :16;
|
||||
unsigned int _reduceds : 2;
|
||||
unsigned int _depth : 8;
|
||||
unsigned int _optimalMin :16;
|
||||
unsigned int _optimalMax :16;
|
||||
unsigned int _reduceds : 2;
|
||||
unsigned int _rpDistance : 4;
|
||||
DbU::Unit _sourcePosition;
|
||||
DbU::Unit _targetPosition;
|
||||
Interval _userConstraints;
|
||||
|
@ -484,6 +490,7 @@ namespace Anabatic {
|
|||
inline bool AutoSegment::getConstraints ( Interval& i ) const { return getConstraints(i.getVMin(),i.getVMax()); }
|
||||
inline AutoSegment* AutoSegment::getCanonical ( Interval& i ) { return getCanonical(i.getVMin(),i.getVMax()); }
|
||||
inline unsigned int AutoSegment::getDepth () const { return _depth; }
|
||||
inline unsigned int AutoSegment::getRpDistance () const { return _rpDistance; }
|
||||
inline DbU::Unit AutoSegment::getPitch () const { return Session::getPitch(getDepth(),Flags::NoFlags); }
|
||||
inline DbU::Unit AutoSegment::getAxis () const { return isHorizontal()?base()->getY():base()->getX(); }
|
||||
inline DbU::Unit AutoSegment::getOrigin () const { return isHorizontal()?_gcell->getYMin():_gcell->getXMin(); }
|
||||
|
@ -503,13 +510,15 @@ namespace Anabatic {
|
|||
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
|
||||
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
|
||||
inline bool AutoSegment::isLocal () const { return not (_flags & SegGlobal); }
|
||||
inline bool AutoSegment::isUnbreakable () const { return _flags & SegUnbreakable; }
|
||||
inline bool AutoSegment::isNonPref () const { return _flags & SegNonPref; }
|
||||
inline bool AutoSegment::isBipoint () const { return _flags & SegBipoint; }
|
||||
inline bool AutoSegment::isWeakTerminal () const { return _flags & SegWeakTerminal; }
|
||||
inline bool AutoSegment::isWeakTerminal1 () const { return _flags & SegWeakTerminal1; }
|
||||
inline bool AutoSegment::isWeakTerminal2 () const { return _flags & SegWeakTerminal2; }
|
||||
inline bool AutoSegment::isWeakTerminal () const { return (_rpDistance < 2); }
|
||||
inline bool AutoSegment::isWeakTerminal1 () const { return (_rpDistance == 1); }
|
||||
inline bool AutoSegment::isWeakTerminal2 () const { return (_rpDistance == 2); }
|
||||
inline bool AutoSegment::isSourceTerminal () const { return _flags & SegSourceTerminal; }
|
||||
inline bool AutoSegment::isTargetTerminal () const { return _flags & SegTargetTerminal; }
|
||||
inline bool AutoSegment::isTerminal () const { return _flags & SegStrongTerminal; }
|
||||
inline bool AutoSegment::isTerminal () const { return (_rpDistance == 0); }
|
||||
inline bool AutoSegment::isDrag () const { return _flags & SegDrag; }
|
||||
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
|
||||
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
|
||||
|
@ -537,6 +546,7 @@ namespace Anabatic {
|
|||
|
||||
inline uint64_t AutoSegment::getFlags () const { return _flags; }
|
||||
inline uint64_t AutoSegment::_getFlags () const { return _flags; }
|
||||
inline void AutoSegment::setRpDistance ( unsigned int distance ) { _rpDistance=distance; }
|
||||
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
|
||||
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
|
||||
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace Anabatic {
|
|||
static const BaseFlags ChannelRow ; // = (1 << 13);
|
||||
static const BaseFlags HRailGCell ; // = (1 << 14);
|
||||
static const BaseFlags VRailGCell ; // = (1 << 15);
|
||||
static const BaseFlags GoStraight ; // = (1 << 16);
|
||||
// Flags for Edge objects states only.
|
||||
static const BaseFlags NullCapacity ; // = (1 << 5);
|
||||
static const BaseFlags InfiniteCapacity ; // = (1 << 6);
|
||||
|
@ -99,6 +100,7 @@ namespace Anabatic {
|
|||
static const BaseFlags CheckLowUpDensity ;
|
||||
static const BaseFlags NoUpdate ;
|
||||
static const BaseFlags NorthPath ;
|
||||
static const BaseFlags UseNonPref ;
|
||||
public:
|
||||
inline Flags ( uint64_t flags = NoFlags );
|
||||
inline Flags ( const Hurricane::BaseFlags& );
|
||||
|
|
|
@ -136,7 +136,6 @@ namespace Anabatic {
|
|||
inline bool Edge::isVertical () const { return _flags.isset(Flags::Vertical); }
|
||||
inline bool Edge::isHorizontal () const { return _flags.isset(Flags::Horizontal); }
|
||||
inline bool Edge::hasNet ( const Net* owner ) const { return getSegment(owner); }
|
||||
inline unsigned int Edge::getCapacity () const { return (_capacities) ? _capacities->getCapacity()-_reservedCapacity : 0; }
|
||||
inline unsigned int Edge::getCapacity ( size_t depth ) const { return (_capacities) ? _capacities->getCapacity(depth) : 0; }
|
||||
inline unsigned int Edge::getReservedCapacity () const { return _reservedCapacity; }
|
||||
inline unsigned int Edge::getRealOccupancy () const { return _realOccupancy; }
|
||||
|
@ -156,6 +155,12 @@ namespace Anabatic {
|
|||
inline Flags& Edge::flags () { return _flags; }
|
||||
inline Flags& Edge::setFlags ( Flags mask ) { _flags |= mask; return _flags; }
|
||||
inline void Edge::reserveCapacity ( int delta ) { _reservedCapacity = ((int)_reservedCapacity+delta > 0) ? _reservedCapacity+delta : 0; }
|
||||
|
||||
inline unsigned int Edge::getCapacity () const
|
||||
{
|
||||
if (not _capacities) return 0;
|
||||
return (_capacities->getCapacity() > (int)_reservedCapacity) ? _capacities->getCapacity()-_reservedCapacity : 0;
|
||||
}
|
||||
|
||||
} // Anabatic namespace.
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ namespace Anabatic {
|
|||
inline bool isMatrix () const;
|
||||
inline bool isRow () const;
|
||||
inline bool isIoPad () const;
|
||||
inline bool isGoStraight () const;
|
||||
inline bool isHRail () const;
|
||||
inline bool isVRail () const;
|
||||
inline bool isStdCellRow () const;
|
||||
|
@ -341,6 +342,7 @@ namespace Anabatic {
|
|||
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
|
||||
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
|
||||
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
|
||||
inline bool GCell::isGoStraight () const { return _flags & Flags::GoStraight; }
|
||||
inline bool GCell::isHRail () const { return _flags & Flags::HRailGCell; }
|
||||
inline bool GCell::isVRail () const { return _flags & Flags::VRailGCell; }
|
||||
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
|
||||
|
|
|
@ -98,6 +98,8 @@ namespace Anabatic {
|
|||
, WestBound = (1 << 14)
|
||||
, EastBound = (1 << 15)
|
||||
, Middle = (1 << 16)
|
||||
, UseNonPref = (1 << 17)
|
||||
, HBothAccess = HAccess|HAccessEW
|
||||
, SouthWest = SouthBound|WestBound
|
||||
, NorthEast = NorthBound|EastBound
|
||||
};
|
||||
|
|
|
@ -241,6 +241,7 @@ symbolicLayersExtensionsTable = \
|
|||
, ('METAL3.metal3.extention.cap' , l( 1.0))
|
||||
, ('METAL4.minimum.width' , l( 1.0))
|
||||
, ('METAL4.metal4.extention.cap' , l( 1.0))
|
||||
, ('METAL4.minimalSpacing' , l( 3.0))
|
||||
, ('METAL5.minimum.width' , l( 2.0))
|
||||
, ('METAL5.metal5.extention.cap' , l( 1.0))
|
||||
, ('METAL6.minimum.width' , l( 2.0))
|
||||
|
|
|
@ -9,6 +9,7 @@ execfile( helpers.sysConfDir+'/common/kite.conf' )
|
|||
|
||||
parametersTable = \
|
||||
( ('lefImport.minTerminalWidth' ,TypeDouble ,0.0 )
|
||||
, ('katabatic.routingGauge' ,TypeString , 'sxlib' )
|
||||
, ("katabatic.globalLengthThreshold",TypeInt ,1450 ) # Katabatic parameters.
|
||||
, ("katabatic.saturateRatio" ,TypePercentage,80 )
|
||||
, ("katabatic.saturateRp" ,TypeInt ,8 )
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
|
||||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2013, All Rights Reserved
|
||||
// Copyright (c) Sorbonne Universite 2008-2019, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | Alliance / Hurricane Interface |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./Histogram.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
@ -31,6 +30,7 @@ namespace CRL {
|
|||
using std::ofstream;
|
||||
using std::ostringstream;
|
||||
using std::setprecision;
|
||||
using std::setw;
|
||||
using std::vector;
|
||||
using Hurricane::Record;
|
||||
|
||||
|
@ -41,13 +41,16 @@ namespace CRL {
|
|||
, _mainTitle ()
|
||||
, _titles (nbSets)
|
||||
, _colors (nbSets)
|
||||
, _indents (nbSets)
|
||||
, _sets (nbSets)
|
||||
, _totalSamples (nbSets)
|
||||
, _fileExtension()
|
||||
{
|
||||
size_t binSize = (size_t)rint ( _range / _step );
|
||||
for ( size_t iset=0 ; iset<nbSets ; ++iset ) {
|
||||
_sets[iset] = vector<float>(binSize);
|
||||
if (_range != 0.0) {
|
||||
size_t binSize = (size_t)rint( _range / _step );
|
||||
for ( size_t iset=0 ; iset<nbSets ; ++iset ) {
|
||||
_sets[iset] = vector<float>( binSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,10 +61,16 @@ namespace CRL {
|
|||
|
||||
void Histogram::addSample ( double sample, size_t iset )
|
||||
{
|
||||
if ( iset >= _sets.size() ) return;
|
||||
if (iset >= _sets.size()) return;
|
||||
|
||||
size_t binIndex = (size_t)rint ( sample / _step );
|
||||
if ( binIndex >= _sets.front().size() ) binIndex = _sets.front().size() - 1;
|
||||
size_t binIndex = (size_t)rint( sample / _step );
|
||||
if (_range != 0.0) {
|
||||
if (binIndex >= _sets.front().size()) binIndex = _sets.front().size() - 1;
|
||||
} else {
|
||||
while ( _sets.front().size() < binIndex + 1) {
|
||||
for ( vector<float>& rset : _sets ) rset.push_back( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
_sets [iset][binIndex] += 1.0;
|
||||
_totalSamples[iset]++;
|
||||
|
@ -101,7 +110,38 @@ namespace CRL {
|
|||
}
|
||||
|
||||
|
||||
void Histogram::toFile ( const string& path )
|
||||
string Histogram::toString ( size_t iset )
|
||||
{
|
||||
if (iset >= _sets.size()) return "";
|
||||
|
||||
ostringstream s;
|
||||
|
||||
size_t titleWidth = _titles[iset].size();
|
||||
|
||||
string hline = _indents[iset] + "+-" + string(titleWidth,'-') + "-+-------------+----+\n";
|
||||
string tline = _indents[iset] + "| " + _titles[iset] + " | Count | % |\n";
|
||||
|
||||
s << hline << tline << hline;
|
||||
|
||||
for ( size_t i=0 ; i<_sets[iset].size() ; ++i ) {
|
||||
float value = _sets[iset][i];
|
||||
if ((value == 0.0) and (_range == 0.0)) continue;
|
||||
|
||||
size_t percent = value*100.0 / _totalSamples[iset];
|
||||
s << _indents[iset]
|
||||
<< "| " << setw(titleWidth) << (size_t)(_step*i)
|
||||
<< " | " << setw(11) << (size_t)(value)
|
||||
<< " | " << setw( 2) << percent
|
||||
<< " | " << string( percent, '*' )
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
s << hline;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
void Histogram::toFile ( string path )
|
||||
{
|
||||
ofstream fd ( path.c_str() );
|
||||
toStream ( fd );
|
||||
|
@ -109,7 +149,7 @@ namespace CRL {
|
|||
}
|
||||
|
||||
|
||||
void Histogram::toGnuplot ( const string& basename )
|
||||
void Histogram::toGnuplot ( string basename )
|
||||
{
|
||||
Utilities::Path datFile ( basename+_fileExtension+".dat" );
|
||||
toFile ( datFile.toString() );
|
||||
|
|
|
@ -1,30 +1,21 @@
|
|||
|
||||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
||||
// Copyright (c) Sorbonne Universite 2008-2019, All Rights Reserved
|
||||
//
|
||||
// ===================================================================
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// x-----------------------------------------------------------------x
|
||||
// | |
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | Alliance / Hurricane Interface |
|
||||
// | |
|
||||
// | Author : Jean-Paul Chaput |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./Histogram.h" |
|
||||
// | *************************************************************** |
|
||||
// | U p d a t e s |
|
||||
// | |
|
||||
// x-----------------------------------------------------------------x
|
||||
// | C++ Header : "./crlcore/Histogram.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef __CRL_HISTOGRAM__
|
||||
#define __CRL_HISTOGRAM__
|
||||
#ifndef CRL_HISTOGRAM_H
|
||||
#define CRL_HISTOGRAM_H
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
@ -40,15 +31,17 @@ namespace CRL {
|
|||
public:
|
||||
Histogram ( double range, double step, size_t nbSets );
|
||||
~Histogram ();
|
||||
inline void setMainTitle ( const std::string& );
|
||||
inline void setTitle ( const std::string&, size_t iset );
|
||||
inline void setColor ( const std::string&, size_t iset );
|
||||
inline void setMainTitle ( std::string );
|
||||
inline void setTitle ( std::string, size_t iset );
|
||||
inline void setColor ( std::string, size_t iset );
|
||||
inline void setIndent ( std::string, size_t iset );
|
||||
void addSample ( double, size_t iset );
|
||||
inline void setFileExtension ( const std::string& );
|
||||
inline void setFileExtension ( std::string );
|
||||
float getYRange () const;
|
||||
void toStream ( std::ostream& );
|
||||
void toFile ( const std::string& );
|
||||
void toGnuplot ( const std::string& basename );
|
||||
std::string toString ( size_t iset );
|
||||
void toFile ( std::string );
|
||||
void toGnuplot ( std::string basename );
|
||||
void normalize ( size_t iset );
|
||||
std::string _getString () const;
|
||||
Hurricane::Record* _getRecord () const;
|
||||
|
@ -58,6 +51,7 @@ namespace CRL {
|
|||
std::string _mainTitle;
|
||||
std::vector< std::string > _titles;
|
||||
std::vector< std::string > _colors;
|
||||
std::vector< std::string > _indents;
|
||||
std::vector< std::vector<float> > _sets;
|
||||
std::vector< int > _totalSamples;
|
||||
std::string _fileExtension;
|
||||
|
@ -65,10 +59,11 @@ namespace CRL {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline void Histogram::setMainTitle ( const std::string& title ) { _mainTitle=title; }
|
||||
inline void Histogram::setTitle ( const std::string& title, size_t iset ) { if (iset<_titles.size()) _titles[iset] = title; }
|
||||
inline void Histogram::setColor ( const std::string& color, size_t iset ) { if (iset<_colors.size()) _colors[iset] = color; }
|
||||
inline void Histogram::setFileExtension ( const std::string& extension ) { _fileExtension=extension; }
|
||||
inline void Histogram::setMainTitle ( std::string title ) { _mainTitle=title; }
|
||||
inline void Histogram::setTitle ( std::string title , size_t iset ) { if (iset<_titles .size()) _titles[iset ] = title; }
|
||||
inline void Histogram::setColor ( std::string color , size_t iset ) { if (iset<_colors .size()) _colors[iset ] = color; }
|
||||
inline void Histogram::setIndent ( std::string indent, size_t iset ) { if (iset<_indents.size()) _indents[iset] = indent; }
|
||||
inline void Histogram::setFileExtension ( std::string extension ) { _fileExtension=extension; }
|
||||
|
||||
|
||||
template<>
|
||||
|
@ -80,7 +75,7 @@ namespace CRL {
|
|||
inline Histogram* getData () const;
|
||||
inline void setData ( Histogram* );
|
||||
virtual std::string toString () const;
|
||||
virtual void toGnuplot ( const std::string& basename ) const;
|
||||
virtual void toGnuplot ( std::string basename ) const;
|
||||
virtual std::string _getString () const;
|
||||
virtual Record* _getRecord () const;
|
||||
private:
|
||||
|
@ -102,7 +97,7 @@ namespace CRL {
|
|||
std::string Measure<Histogram>::toString () const
|
||||
{ return "Unsupported"; }
|
||||
|
||||
void Measure<Histogram>::toGnuplot ( const std::string& basename ) const
|
||||
void Measure<Histogram>::toGnuplot ( std::string basename ) const
|
||||
{ _data->toGnuplot ( basename ); }
|
||||
|
||||
std::string Measure<Histogram>::_getString () const
|
||||
|
@ -118,9 +113,9 @@ namespace CRL {
|
|||
}
|
||||
|
||||
|
||||
} // End of CRL namespace.
|
||||
} // CRL namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(CRL::Histogram)
|
||||
|
||||
#endif // __CRL_HISTOGRAM__
|
||||
#endif // CRL_HISTOGRAM_H
|
||||
|
|
|
@ -97,7 +97,7 @@ def ScriptMain ( **kw ):
|
|||
conf = chip.Configuration.ChipConf( {}, cell, editor )
|
||||
|
||||
if cell.getAbutmentBox().isEmpty():
|
||||
spaceMargin = Cfg.getParamPercentage('etesian.spaceMargin').asPercentage() / 100.0 + 0.02
|
||||
spaceMargin = Cfg.getParamPercentage('etesian.spaceMargin').asPercentage() / 100.0 + 0.01
|
||||
aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0
|
||||
clocktree.ClockTree.computeAbutmentBox( cell, spaceMargin, aspectRatio, conf.cellGauge )
|
||||
if editor: editor.fit()
|
||||
|
|
|
@ -29,6 +29,7 @@ from Hurricane import Net
|
|||
from Hurricane import Contact
|
||||
from Hurricane import Horizontal
|
||||
from Hurricane import Vertical
|
||||
from Hurricane import Pad
|
||||
import CRL
|
||||
from CRL import RoutingLayerGauge
|
||||
from helpers import trace
|
||||
|
@ -421,6 +422,20 @@ class VerticalSide ( Side ):
|
|||
, sideXMin
|
||||
, sideXMax
|
||||
)
|
||||
|
||||
depth -= 2
|
||||
if depth > 0:
|
||||
blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer()
|
||||
pitch = routingGauge.getLayerPitch(depth)
|
||||
|
||||
for chunk in spans.chunks:
|
||||
Horizontal.create( self.blockageNet
|
||||
, blockageLayer
|
||||
, (chunk.getVMax() + chunk.getVMin())/2
|
||||
, chunk.getVMax() - chunk.getVMin() + pitch*2
|
||||
, sideXMin
|
||||
, sideXMax
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
|
@ -542,6 +557,11 @@ class Corona ( object ):
|
|||
contactDepth = self.verticalDepth
|
||||
|
||||
UpdateSession.open()
|
||||
blBox = Box()
|
||||
brBox = Box()
|
||||
tlBox = Box()
|
||||
trBox = Box()
|
||||
|
||||
for i in range(self.railsNb):
|
||||
xBL = self.westSide .getRail(i).axis
|
||||
yBL = self.southSide.getRail(i).axis
|
||||
|
@ -549,6 +569,11 @@ class Corona ( object ):
|
|||
yTR = self.northSide.getRail(i).axis
|
||||
net = self.getRailNet( i )
|
||||
|
||||
blBox.merge( xBL, yBL )
|
||||
brBox.merge( xTR, yBL )
|
||||
tlBox.merge( xBL, yTR )
|
||||
trBox.merge( xTR, yTR )
|
||||
|
||||
self.routingGauge.getContactLayer(contactDepth)
|
||||
self.corners[chip.SouthWest].append(
|
||||
Contact.create( net
|
||||
|
@ -586,5 +611,19 @@ class Corona ( object ):
|
|||
|
||||
self.westSide.addBlockages()
|
||||
self.eastSide.addBlockages()
|
||||
|
||||
blBox.inflate( self.hRailWidth, self.vRailWidth )
|
||||
brBox.inflate( self.hRailWidth, self.vRailWidth )
|
||||
tlBox.inflate( self.hRailWidth, self.vRailWidth )
|
||||
trBox.inflate( self.hRailWidth, self.vRailWidth )
|
||||
|
||||
for depth in range( 1, self.conf.gaugeConf.topLayerDepth + 1 ):
|
||||
blockageLayer = self.routingGauge.getRoutingLayer(depth).getBlockageLayer()
|
||||
|
||||
Pad.create( self.blockageNet, blockageLayer, blBox )
|
||||
Pad.create( self.blockageNet, blockageLayer, brBox )
|
||||
Pad.create( self.blockageNet, blockageLayer, tlBox )
|
||||
Pad.create( self.blockageNet, blockageLayer, trBox )
|
||||
|
||||
UpdateSession.close()
|
||||
return
|
||||
|
|
|
@ -42,6 +42,7 @@ try:
|
|||
import helpers
|
||||
from helpers import trace
|
||||
from helpers.io import ErrorMessage
|
||||
import Etesian
|
||||
import Unicorn
|
||||
import plugins
|
||||
from clocktree.RSMT import RSMT
|
||||
|
@ -585,36 +586,40 @@ class HTreeNode ( object ):
|
|||
|
||||
|
||||
def computeAbutmentBox ( cell, spaceMargin, aspectRatio, cellGauge ):
|
||||
sliceHeight = DbU.toLambda( cellGauge.getSliceHeight() )
|
||||
|
||||
instancesNb = 0
|
||||
cellLength = 0
|
||||
for occurrence in cell.getLeafInstanceOccurrences():
|
||||
instance = occurrence.getEntity()
|
||||
instancesNb += 1
|
||||
cellLength += int( DbU.toLambda(instance.getMasterCell().getAbutmentBox().getWidth()) )
|
||||
|
||||
# ar = x/y S = x*y = spaceMargin*SH x=S/y ar = S/y^2
|
||||
# y = sqrt(S/AR)
|
||||
gcellLength = float(cellLength)*(1+spaceMargin) / sliceHeight
|
||||
rows = math.sqrt( gcellLength/aspectRatio )
|
||||
if math.trunc(rows) != rows: rows = math.trunc(rows) + 1
|
||||
else: rows = math.trunc(rows)
|
||||
columns = gcellLength / rows
|
||||
if math.trunc(columns) != columns: columns = math.trunc(columns) + 1
|
||||
else: columns = math.trunc(columns)
|
||||
|
||||
print ' o Creating abutment box (margin:%.1f%%, aspect ratio:%.1f%%, g-length:%.1fl)' \
|
||||
% (spaceMargin*100.0,aspectRatio*100.0,(cellLength/sliceHeight))
|
||||
print ' - GCell grid: [%dx%d]' % (columns,rows)
|
||||
# sliceHeight = DbU.toLambda( cellGauge.getSliceHeight() )
|
||||
#
|
||||
# instancesNb = 0
|
||||
# cellLength = 0
|
||||
# for occurrence in cell.getLeafInstanceOccurrences():
|
||||
# instance = occurrence.getEntity()
|
||||
# instancesNb += 1
|
||||
# cellLength += int( DbU.toLambda(instance.getMasterCell().getAbutmentBox().getWidth()) )
|
||||
#
|
||||
# # ar = x/y S = x*y = spaceMargin*SH x=S/y ar = S/y^2
|
||||
# # y = sqrt(S/AR)
|
||||
# gcellLength = float(cellLength)*(1+spaceMargin) / sliceHeight
|
||||
# rows = math.sqrt( gcellLength/aspectRatio )
|
||||
# if math.trunc(rows) != rows: rows = math.trunc(rows) + 1
|
||||
# else: rows = math.trunc(rows)
|
||||
# columns = gcellLength / rows
|
||||
# if math.trunc(columns) != columns: columns = math.trunc(columns) + 1
|
||||
# else: columns = math.trunc(columns)
|
||||
#
|
||||
# print ' o Creating abutment box (margin:%.1f%%, aspect ratio:%.1f%%, g-length:%.1fl)' \
|
||||
# % (spaceMargin*100.0,aspectRatio*100.0,(cellLength/sliceHeight))
|
||||
# print ' - GCell grid: [%dx%d]' % (columns,rows)
|
||||
|
||||
UpdateSession.open()
|
||||
abutmentBox = Box( DbU.fromLambda(0)
|
||||
, DbU.fromLambda(0)
|
||||
, DbU.fromLambda(columns*sliceHeight)
|
||||
, DbU.fromLambda(rows *sliceHeight)
|
||||
)
|
||||
cell.setAbutmentBox( abutmentBox )
|
||||
etesian = Etesian.EtesianEngine.create( cell )
|
||||
etesian.setDefaultAb()
|
||||
etesian.destroy()
|
||||
|
||||
#abutmentBox = Box( DbU.fromLambda(0)
|
||||
# , DbU.fromLambda(0)
|
||||
# , DbU.fromLambda(columns*sliceHeight)
|
||||
# , DbU.fromLambda(rows *sliceHeight)
|
||||
# )
|
||||
#cell.setAbutmentBox( abutmentBox )
|
||||
UpdateSession.close()
|
||||
|
||||
return abutmentBox
|
||||
return cell.getAbutmentBox()
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Universite 2019-2019, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | E t e s i a n - A n a l y t i c P l a c e r |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./BloatCells.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "etesian/EtesianEngine.h"
|
||||
|
||||
|
||||
namespace Etesian {
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::DbU;
|
||||
|
||||
|
||||
BloatCell::BloatCell ( std::string name )
|
||||
: _name(name)
|
||||
{ }
|
||||
|
||||
|
||||
BloatCell::~BloatCell ()
|
||||
{ }
|
||||
|
||||
|
||||
BloatKey::BloatKey ( string key )
|
||||
: BloatCell(key)
|
||||
{ }
|
||||
|
||||
|
||||
BloatKey::~BloatKey ()
|
||||
{ }
|
||||
|
||||
|
||||
DbU::Unit BloatKey::getDx ( const Cell*, const EtesianEngine* ) const
|
||||
{
|
||||
cerr << Error( "BloatKey::getAb() must never be called (\"%s\").", getName().c_str() ) << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
BloatDisabled::BloatDisabled ()
|
||||
: BloatCell("disabled")
|
||||
{ }
|
||||
|
||||
|
||||
BloatDisabled::~BloatDisabled ()
|
||||
{ }
|
||||
|
||||
|
||||
DbU::Unit BloatDisabled::getDx ( const Cell* cell, const EtesianEngine* ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
BloatNsxlib::BloatNsxlib ()
|
||||
: BloatCell("nsxlib")
|
||||
{ }
|
||||
|
||||
|
||||
BloatNsxlib::~BloatNsxlib ()
|
||||
{ }
|
||||
|
||||
|
||||
DbU::Unit BloatNsxlib::getDx ( const Cell* cell, const EtesianEngine* etesian ) const
|
||||
{
|
||||
Box ab ( cell->getAbutmentBox() );
|
||||
DbU::Unit vpitch = etesian->getVerticalPitch();;
|
||||
int xsize = (ab.getWidth() + vpitch - 1) / vpitch;
|
||||
|
||||
if (xsize < 6) return vpitch*2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool BloatCells::select ( std::string profile )
|
||||
{
|
||||
BloatKey key ( profile );
|
||||
|
||||
auto ibloat = _bloatCells.find( &key );
|
||||
if (ibloat != _bloatCells.end()) {
|
||||
_selected = *ibloat;
|
||||
return true;
|
||||
}
|
||||
|
||||
cerr << Warning( "BloatCells::select(): No profile named \"%s\", using \"disabled\"."
|
||||
, profile.c_str()
|
||||
) << endl;
|
||||
|
||||
return select( "disabled" );
|
||||
}
|
||||
|
||||
|
||||
Box BloatCells::getAb ( const Cell* cell )
|
||||
{
|
||||
DbU::Unit dx = _selected->getDx( cell, _etesian );
|
||||
|
||||
_dxSpace += dx;
|
||||
Box ab = cell->getAbutmentBox();
|
||||
return ab.inflate( 0, 0, dx, 0 );
|
||||
}
|
||||
|
||||
|
||||
} // Etesian namespace.
|
|
@ -12,6 +12,7 @@
|
|||
)
|
||||
set( includes etesian/Configuration.h
|
||||
etesian/FeedCells.h
|
||||
etesian/BloatCells.h
|
||||
etesian/EtesianEngine.h
|
||||
etesian/GraphicEtesianEngine.h
|
||||
)
|
||||
|
@ -22,6 +23,7 @@
|
|||
set( cpps Configuration.cpp
|
||||
AddFeeds.cpp
|
||||
FeedCells.cpp
|
||||
BloatCells.cpp
|
||||
EtesianEngine.cpp
|
||||
GraphicEtesianEngine.cpp
|
||||
)
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace Etesian {
|
|||
, _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() )
|
||||
, _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.0)->asDouble() )
|
||||
, _feedNames ( Cfg::getParamString ("etesian.feedNames" ,"tie_x0,rowend_x0")->asString() )
|
||||
, _bloat ( Cfg::getParamString ("etesian.bloat" ,"disabled" )->asString() )
|
||||
{
|
||||
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
|
||||
if (cg == NULL) {
|
||||
|
@ -88,6 +89,7 @@ namespace Etesian {
|
|||
, _spaceMargin ( other._spaceMargin )
|
||||
, _aspectRatio ( other._aspectRatio )
|
||||
, _feedNames ( other._feedNames )
|
||||
, _bloat ( other._bloat )
|
||||
{
|
||||
if (other._rg) _rg = other._rg->getClone();
|
||||
if (other._cg) _cg = other._cg->getClone();
|
||||
|
@ -114,6 +116,7 @@ namespace Etesian {
|
|||
cmess1 << Dots::asBool (" - Routing driven",_routingDriven) << endl;
|
||||
cmess1 << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl;
|
||||
cmess1 << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
|
||||
cmess1 << Dots::asString (" - Bloat model" ,_bloat ) << endl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,6 +144,8 @@ namespace Etesian {
|
|||
record->add ( getSlot( "_spreadingConf" , (int)_spreadingConf ) );
|
||||
record->add ( getSlot( "_spaceMargin" , _spaceMargin ) );
|
||||
record->add ( getSlot( "_aspectRatio" , _aspectRatio ) );
|
||||
record->add ( getSlot( "_feedNames" , _feedNames ) );
|
||||
record->add ( getSlot( "_bloat" , _bloat ) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "crlcore/Measures.h"
|
||||
#include "crlcore/AllianceFramework.h"
|
||||
#include "etesian/EtesianEngine.h"
|
||||
#include "etesian/FeedCells.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
@ -265,6 +264,7 @@ namespace Etesian {
|
|||
, _idsToInsts ()
|
||||
, _viewer (NULL)
|
||||
, _feedCells (this)
|
||||
, _bloatCells (this)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,8 @@ namespace Etesian {
|
|||
cmess2 << " o ISPD benchmark <" << getCell()->getName()
|
||||
<< ">, no feed cells will be added." << endl;
|
||||
} else {
|
||||
_bloatCells.select( getConfiguration()->getBloat() );
|
||||
|
||||
string feedNames = getConfiguration()->getFeedNames();
|
||||
char separator = ',';
|
||||
|
||||
|
@ -349,6 +351,7 @@ namespace Etesian {
|
|||
|
||||
void EtesianEngine::setDefaultAb ()
|
||||
{
|
||||
_bloatCells.resetDxSpace();
|
||||
double spaceMargin = getSpaceMargin();
|
||||
double aspectRatio = getAspectRatio();
|
||||
size_t instanceNb = 0;
|
||||
|
@ -369,10 +372,13 @@ namespace Etesian {
|
|||
continue;
|
||||
}
|
||||
|
||||
cellLength += DbU::toLambda( masterCell->getAbutmentBox().getWidth() );
|
||||
cellLength += DbU::toLambda( _bloatCells.getAb( masterCell ).getWidth() );
|
||||
instanceNb += 1;
|
||||
}
|
||||
|
||||
double bloatLength = DbU::toLambda( _bloatCells.getDxSpace() );
|
||||
double bloatMargin = ( cellLength / (cellLength - bloatLength) ) - 1.0;
|
||||
|
||||
double gcellLength = cellLength*(1.0+spaceMargin) / DbU::toLambda( getSliceHeight() );
|
||||
double rows = std::ceil( sqrt( gcellLength/aspectRatio ) );
|
||||
double columns = std::ceil( gcellLength / rows );
|
||||
|
@ -398,6 +404,8 @@ namespace Etesian {
|
|||
<< "% aspect ratio:" << (aspectRatio*100.0)
|
||||
<< "% g-length:" << (cellLength/DbU::toLambda(getSliceHeight()))
|
||||
<< ")" << endl;
|
||||
cmess1 << " - Bloat space margin: "
|
||||
<< setprecision(4) << (bloatMargin*100.0) << "%." << endl;
|
||||
cmess1 << " - " << getCell()->getAbutmentBox() << endl;
|
||||
cmess1 << " - GCell grid: [" << (int)columns << "x" << (int)rows << "]" << endl;
|
||||
}
|
||||
|
@ -538,7 +546,7 @@ namespace Etesian {
|
|||
continue;
|
||||
}
|
||||
|
||||
Box instanceAb = masterCell->getAbutmentBox();
|
||||
Box instanceAb = _bloatCells.getAb( masterCell );
|
||||
|
||||
Transformation instanceTransf = instance->getTransformation();
|
||||
occurrence.getPath().getTransformation().applyOn( instanceTransf );
|
||||
|
@ -551,6 +559,8 @@ namespace Etesian {
|
|||
int_t xpos = instanceAb.getXMin() / vpitch;
|
||||
int_t ypos = instanceAb.getYMin() / hpitch;
|
||||
|
||||
//if (xsize < 6) xsize += 2;
|
||||
|
||||
// if ( (ysize != 1) and not instance->isFixed() ) {
|
||||
// cerr << Error( "EtesianEngine::toColoquinte(): Instance \"%s\" of \"%s\" is a block (height: %d)."
|
||||
// , instanceName.c_str()
|
||||
|
@ -558,6 +568,9 @@ namespace Etesian {
|
|||
// , ysize ) << endl;
|
||||
// }
|
||||
|
||||
// cerr << instance << " size:(" << xsize << " " << ysize
|
||||
// << ") pos:(" << xpos << " " << ypos << ")" << endl;
|
||||
|
||||
instances[instanceId].size = point<int_t>( xsize, ysize );
|
||||
instances[instanceId].list_index = instanceId;
|
||||
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize);
|
||||
|
@ -603,6 +616,8 @@ namespace Etesian {
|
|||
|
||||
nets[netId] = temporary_net( netId, 1 );
|
||||
|
||||
//cerr << "+ " << net << endl;
|
||||
|
||||
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
string insName = extractInstanceName( rp );
|
||||
Point offset = extractRpOffset ( rp );
|
||||
|
@ -616,6 +631,8 @@ namespace Etesian {
|
|||
} else {
|
||||
pins.push_back( temporary_pin( point<int_t>(xpin,ypin), (*iid).second, netId ) );
|
||||
}
|
||||
|
||||
//cerr << "| " << rp << " pos:(" << xpin << " " << ypin << ")" << endl;
|
||||
}
|
||||
|
||||
netId++;
|
||||
|
|
|
@ -63,6 +63,9 @@ extern "C" {
|
|||
// +=================================================================+
|
||||
|
||||
|
||||
DirectVoidMethod(EtesianEngine,etesian,setDefaultAb)
|
||||
|
||||
|
||||
static PyObject* PyEtesianEngine_get ( PyObject*, PyObject* args )
|
||||
{
|
||||
cdebug_log(34,0) << "PyEtesianEngine_get()" << endl;
|
||||
|
@ -127,6 +130,25 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyEtesianEngine_selectBloat ( PyEtesianEngine* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(34,0) << "PyEtesianEngine_selectBloat ()" << endl;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD( "EtesianEngine.selectBloat()" )
|
||||
|
||||
const char* profile = NULL;
|
||||
if (not PyArg_ParseTuple(args,"s:EtesianEngine.selectBloat()",&profile)) {
|
||||
PyErr_SetString( ConstructorError, "Bad parameters given to EtesianEngine.selectBloat()." );
|
||||
return NULL;
|
||||
}
|
||||
etesian->selectBloat( profile );
|
||||
HCATCH
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyEtesianEngine_place ( PyEtesianEngine* self )
|
||||
{
|
||||
cdebug_log(34,0) << "PyEtesianEngine_place()" << endl;
|
||||
|
@ -159,6 +181,10 @@ extern "C" {
|
|||
, "Create an Etesian engine on this cell." }
|
||||
, { "setViewer" , (PyCFunction)PyEtesianEngine_setViewer , METH_VARARGS
|
||||
, "Associate a Viewer to this EtesianEngine." }
|
||||
, { "selectBloat" , (PyCFunction)PyEtesianEngine_selectBloat , METH_VARARGS
|
||||
, "Select the Cell bloating profile." }
|
||||
, { "setDefaultAb" , (PyCFunction)PyEtesianEngine_setDefaultAb , METH_NOARGS
|
||||
, "Compute and set the abutment box using the aspect ratio and the space margin." }
|
||||
, { "place" , (PyCFunction)PyEtesianEngine_place , METH_NOARGS
|
||||
, "Run the placer (Etesian)." }
|
||||
, { "destroy" , (PyCFunction)PyEtesianEngine_destroy , METH_NOARGS
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Universite 2019-2019, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | E t e s i a n - A n a l y t i c P l a c e r |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./etesian/BloatCells.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef ETESIAN_BLOATCELLS_H
|
||||
#define ETESIAN_BLOATCELLS_H
|
||||
|
||||
#include <set>
|
||||
#include "hurricane/Box.h"
|
||||
#include "hurricane/Cell.h"
|
||||
|
||||
|
||||
namespace Etesian {
|
||||
|
||||
using Hurricane::Box;
|
||||
using Hurricane::Cell;
|
||||
class EtesianEngine;
|
||||
|
||||
|
||||
class BloatCell {
|
||||
public:
|
||||
class Compare {
|
||||
public:
|
||||
inline bool operator() ( const BloatCell* lhs, BloatCell* rhs ) const;
|
||||
inline bool operator() ( std::string lhs, BloatCell* rhs ) const;
|
||||
inline bool operator() ( const BloatCell* lhs, std::string rhs ) const;
|
||||
};
|
||||
public:
|
||||
BloatCell ( std::string );
|
||||
virtual ~BloatCell ();
|
||||
virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const = 0;
|
||||
inline std::string getName () const;
|
||||
private:
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
|
||||
inline bool BloatCell::Compare::operator() ( const BloatCell* lhs, BloatCell* rhs ) const
|
||||
{ return (lhs->getName() < rhs->getName()); }
|
||||
|
||||
inline bool BloatCell::Compare::operator() ( std::string lhs, BloatCell* rhs ) const
|
||||
{ return (lhs < rhs->getName()); }
|
||||
|
||||
inline bool BloatCell::Compare::operator() ( const BloatCell* lhs, std::string rhs ) const
|
||||
{ return (lhs->getName() < rhs); }
|
||||
|
||||
|
||||
inline std::string BloatCell::getName () const { return _name; }
|
||||
|
||||
|
||||
class BloatKey : public BloatCell {
|
||||
public:
|
||||
BloatKey ( std::string );
|
||||
virtual ~BloatKey ();
|
||||
virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const;
|
||||
};
|
||||
|
||||
|
||||
class BloatDisabled : public BloatCell {
|
||||
public:
|
||||
BloatDisabled ();
|
||||
virtual ~BloatDisabled ();
|
||||
virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const;
|
||||
};
|
||||
|
||||
|
||||
class BloatNsxlib : public BloatCell {
|
||||
public:
|
||||
BloatNsxlib ();
|
||||
virtual ~BloatNsxlib ();
|
||||
virtual DbU::Unit getDx ( const Cell*, const EtesianEngine* ) const;
|
||||
};
|
||||
|
||||
|
||||
class BloatCells {
|
||||
public:
|
||||
inline BloatCells ( EtesianEngine* );
|
||||
inline ~BloatCells ();
|
||||
bool select ( std::string );
|
||||
Box getAb ( const Cell* );
|
||||
inline DbU::Unit getDxSpace () const;
|
||||
inline void resetDxSpace ();
|
||||
private:
|
||||
EtesianEngine* _etesian;
|
||||
BloatCell* _selected;
|
||||
std::set<BloatCell*,BloatCell::Compare> _bloatCells;
|
||||
DbU::Unit _dxSpace;
|
||||
};
|
||||
|
||||
|
||||
inline BloatCells::BloatCells ( EtesianEngine* etesian )
|
||||
: _etesian (etesian)
|
||||
, _selected (NULL)
|
||||
, _bloatCells()
|
||||
, _dxSpace (0)
|
||||
{
|
||||
_bloatCells.insert( new BloatDisabled() );
|
||||
_bloatCells.insert( new BloatNsxlib () );
|
||||
select( "disabled" );
|
||||
}
|
||||
|
||||
|
||||
inline BloatCells::~BloatCells ()
|
||||
{
|
||||
for ( BloatCell* bloat : _bloatCells ) delete bloat;
|
||||
}
|
||||
|
||||
|
||||
inline DbU::Unit BloatCells::getDxSpace () const { return _dxSpace; }
|
||||
inline void BloatCells::resetDxSpace () { _dxSpace = 0; }
|
||||
|
||||
|
||||
} // Etesian namespace.
|
||||
|
||||
#endif // ETESIAN_BLOATCELLS_H
|
|
@ -73,6 +73,7 @@ namespace Etesian {
|
|||
inline double getSpaceMargin () const;
|
||||
inline double getAspectRatio () const;
|
||||
inline string getFeedNames () const;
|
||||
inline string getBloat () const;
|
||||
void print ( Cell* ) const;
|
||||
Record* _getRecord () const;
|
||||
string _getString () const;
|
||||
|
@ -88,6 +89,7 @@ namespace Etesian {
|
|||
double _spaceMargin;
|
||||
double _aspectRatio;
|
||||
string _feedNames;
|
||||
string _bloat;
|
||||
private:
|
||||
Configuration ( const Configuration& );
|
||||
Configuration& operator= ( const Configuration& );
|
||||
|
@ -103,6 +105,7 @@ namespace Etesian {
|
|||
inline double Configuration::getSpaceMargin () const { return _spaceMargin; }
|
||||
inline double Configuration::getAspectRatio () const { return _aspectRatio; }
|
||||
inline string Configuration::getFeedNames () const { return _feedNames; }
|
||||
inline string Configuration::getBloat () const { return _bloat; }
|
||||
|
||||
|
||||
} // Etesian namespace.
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace Hurricane {
|
|||
#include "crlcore/ToolEngine.h"
|
||||
#include "etesian/Configuration.h"
|
||||
#include "etesian/FeedCells.h"
|
||||
#include "etesian/BloatCells.h"
|
||||
|
||||
|
||||
namespace Etesian {
|
||||
|
@ -92,6 +93,7 @@ namespace Etesian {
|
|||
inline void useFeed ( Cell* );
|
||||
size_t findYSpin ();
|
||||
void addFeeds ();
|
||||
inline void selectBloat ( std::string );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual std::string _getString () const;
|
||||
virtual std::string _getTypeName () const;
|
||||
|
@ -112,6 +114,7 @@ namespace Etesian {
|
|||
std::vector<Instance*> _idsToInsts;
|
||||
Hurricane::CellViewer* _viewer;
|
||||
FeedCells _feedCells;
|
||||
BloatCells _bloatCells;
|
||||
size_t _yspinSlice0;
|
||||
|
||||
protected:
|
||||
|
@ -146,6 +149,7 @@ namespace Etesian {
|
|||
inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); }
|
||||
inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); }
|
||||
inline const FeedCells& EtesianEngine::getFeedCells () const { return _feedCells; }
|
||||
inline void EtesianEngine::selectBloat ( std::string profile ) { _bloatCells.select(profile); }
|
||||
|
||||
|
||||
// Variables.
|
||||
|
|
|
@ -1528,7 +1528,7 @@ Name Cell::InstanceMap::_getKey(Instance* instance) const
|
|||
unsigned int Cell::InstanceMap::_getHashValue(Name name) const
|
||||
// *******************************************************
|
||||
{
|
||||
return name._getSharedName()->getId() / 8;
|
||||
return name._getSharedName()->getHash() / 8;
|
||||
}
|
||||
|
||||
Instance* Cell::InstanceMap::_getNextElement(Instance* instance) const
|
||||
|
@ -1643,7 +1643,7 @@ Name Cell::PinMap::_getKey(Pin* pin) const
|
|||
unsigned Cell::PinMap::_getHashValue(Name name) const
|
||||
// **************************************************
|
||||
{
|
||||
return (unsigned int)name._getSharedName()->getId() / 8;
|
||||
return (unsigned int)name._getSharedName()->getHash() / 8;
|
||||
}
|
||||
|
||||
Pin* Cell::PinMap::_getNextElement(Pin* pin) const
|
||||
|
|
|
@ -602,65 +602,66 @@ static bool IsConnex(const Occurrence& componentOccurrence1, const Occurrence& c
|
|||
}
|
||||
|
||||
void HyperNet_NetOccurrences::Locator::progress()
|
||||
// *********************************************
|
||||
// **********************************************
|
||||
{
|
||||
if (!_netOccurrenceStack.empty()) {
|
||||
Occurrence netOccurrence = _netOccurrenceStack.top();
|
||||
_netOccurrenceStack.pop();
|
||||
Net* net = (Net*)netOccurrence.getEntity();
|
||||
Path path = netOccurrence.getPath();
|
||||
if (not _netOccurrenceStack.empty()) {
|
||||
Occurrence netOccurrence = _netOccurrenceStack.top();
|
||||
_netOccurrenceStack.pop();
|
||||
Net* net = (Net*)netOccurrence.getEntity();
|
||||
Path path = netOccurrence.getPath();
|
||||
|
||||
if (_doExtraction) {
|
||||
Cell* cell = netOccurrence.getOwnerCell();
|
||||
for_each_component(component, net->getComponents()) {
|
||||
if (!dynamic_cast<Plug*>(component)) {
|
||||
//if (_allowInterruption && !((i++) % 200)) gtk_check_for_interruption();
|
||||
Occurrence occurrence = Occurrence(component, path);
|
||||
Box area = occurrence.getBoundingBox();
|
||||
for_each_occurrence(occurrence2, cell->getOccurrencesUnder(area)) {
|
||||
if (dynamic_cast<Component*>(occurrence2.getEntity())) {
|
||||
Component* component2 = (Component*)occurrence2.getEntity();
|
||||
if (IsConnex(occurrence, occurrence2)) {
|
||||
Occurrence net2Occurrence =
|
||||
Occurrence(component2->getNet(), occurrence2.getPath());
|
||||
if (_netOccurrenceSet.find(net2Occurrence) == _netOccurrenceSet.end()) {
|
||||
_netOccurrenceSet.insert(net2Occurrence);
|
||||
_netOccurrenceStack.push(net2Occurrence);
|
||||
}
|
||||
}
|
||||
}
|
||||
end_for;
|
||||
}
|
||||
if (_doExtraction) {
|
||||
Cell* cell = netOccurrence.getOwnerCell();
|
||||
for ( Component* component : net->getComponents()) {
|
||||
if (not dynamic_cast<Plug*>(component)) {
|
||||
//if (_allowInterruption && !((i++) % 200)) gtk_check_for_interruption();
|
||||
Occurrence occurrence = Occurrence( component, path );
|
||||
Box area = occurrence.getBoundingBox();
|
||||
|
||||
for ( Occurrence occurrence2 : cell->getOccurrencesUnder(area)) {
|
||||
if (dynamic_cast<Component*>(occurrence2.getEntity())) {
|
||||
Component* component2 = static_cast<Component*>( occurrence2.getEntity() );
|
||||
|
||||
if (IsConnex(occurrence,occurrence2)) {
|
||||
Occurrence net2Occurrence =
|
||||
Occurrence( component2->getNet(), occurrence2.getPath() );
|
||||
|
||||
if (_netOccurrenceSet.find(net2Occurrence) == _netOccurrenceSet.end()) {
|
||||
_netOccurrenceSet.insert(net2Occurrence);
|
||||
_netOccurrenceStack.push(net2Occurrence);
|
||||
}
|
||||
}
|
||||
end_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for occurence2.
|
||||
}
|
||||
} // for component*.
|
||||
}
|
||||
|
||||
for_each_plug(plug, net->getPlugs()) {
|
||||
Occurrence occurrence = Occurrence(plug->getMasterNet(), Path(path, plug->getInstance()));
|
||||
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
|
||||
for ( Plug* plug : net->getPlugs() ) {
|
||||
Occurrence occurrence = Occurrence( plug->getMasterNet(), Path(path, plug->getInstance()) );
|
||||
|
||||
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
|
||||
_netOccurrenceSet.insert(occurrence);
|
||||
_netOccurrenceStack.push(occurrence);
|
||||
}
|
||||
}
|
||||
|
||||
if (net->isExternal()) {
|
||||
Instance* instance = path.getTailInstance();
|
||||
if (instance) {
|
||||
Plug* plug = instance->getPlug(net);
|
||||
if (plug) {
|
||||
Net* net = plug->getNet();
|
||||
if (net) {
|
||||
Occurrence occurrence = Occurrence(net, path.getHeadPath());
|
||||
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
|
||||
_netOccurrenceSet.insert(occurrence);
|
||||
_netOccurrenceStack.push(occurrence);
|
||||
}
|
||||
}
|
||||
end_for;
|
||||
}
|
||||
|
||||
if (net->isExternal()) {
|
||||
Instance* instance = path.getTailInstance();
|
||||
if (instance) {
|
||||
Plug* plug = instance->getPlug(net);
|
||||
if (plug) {
|
||||
Net* net = plug->getNet();
|
||||
if (net) {
|
||||
Occurrence occurrence = Occurrence(net, path.getHeadPath());
|
||||
if (_netOccurrenceSet.find(occurrence) == _netOccurrenceSet.end()) {
|
||||
_netOccurrenceSet.insert(occurrence);
|
||||
_netOccurrenceStack.push(occurrence);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if net->isExternal().
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1053,6 +1054,7 @@ void HyperNet_LeafPlugOccurrences::Locator::progress()
|
|||
while(_netOccurrenceLocator.isValid() && !_plugOccurrence.isValid())
|
||||
{
|
||||
Occurrence netOccurrence = _netOccurrenceLocator.getElement();
|
||||
|
||||
_netOccurrenceLocator.progress();
|
||||
Net* net = (Net*)netOccurrence.getEntity();
|
||||
Path path = netOccurrence.getPath();
|
||||
|
|
|
@ -709,7 +709,7 @@ const SharedPath* Instance::SharedPathMap::_getKey(SharedPath* sharedPath) const
|
|||
unsigned Instance::SharedPathMap::_getHashValue(const SharedPath* tailSharedPath) const
|
||||
// ************************************************************************************
|
||||
{
|
||||
return (tailSharedPath) ? (tailSharedPath->getId()/8) : 0;
|
||||
return (tailSharedPath) ? (tailSharedPath->getHash()/8) : 0;
|
||||
}
|
||||
|
||||
SharedPath* Instance::SharedPathMap::_getNextElement(SharedPath* sharedPath) const
|
||||
|
|
|
@ -178,7 +178,7 @@ Name Library::LibraryMap::_getKey(Library* library) const
|
|||
unsigned Library::LibraryMap::_getHashValue(Name name) const
|
||||
// *********************************************************
|
||||
{
|
||||
return name._getSharedName()->getId() / 8;
|
||||
return name._getSharedName()->getHash() / 8;
|
||||
}
|
||||
|
||||
Library* Library::LibraryMap::_getNextElement(Library* library) const
|
||||
|
@ -214,7 +214,7 @@ Name Library::CellMap::_getKey(Cell* cell) const
|
|||
unsigned Library::CellMap::_getHashValue(Name name) const
|
||||
// ******************************************************
|
||||
{
|
||||
return name._getSharedName()->getId() / 8;
|
||||
return name._getSharedName()->getHash() / 8;
|
||||
}
|
||||
|
||||
Cell* Library::CellMap::_getNextElement(Cell* cell) const
|
||||
|
|
|
@ -99,7 +99,7 @@ bool Occurrence::operator<(const Occurrence& occurrence) const
|
|||
if (not _sharedPath) return true;
|
||||
if (not occurrence._sharedPath) return false;
|
||||
|
||||
return _sharedPath->getId() < occurrence._sharedPath->getId();
|
||||
return _sharedPath->getHash() < occurrence._sharedPath->getHash();
|
||||
|
||||
//return ((_entity < occurrence._entity) or
|
||||
// ((_entity == occurrence._entity) and (_sharedPath < occurrence._sharedPath)));
|
||||
|
|
|
@ -30,21 +30,23 @@ namespace Hurricane {
|
|||
// ****************************************************************************************************
|
||||
|
||||
SharedName::SharedNameMap* SharedName::_SHARED_NAME_MAP = NULL;
|
||||
unsigned int SharedName::_idCounter = 0;
|
||||
|
||||
|
||||
SharedName::SharedName ( const string& name )
|
||||
: _id (_idCounter++)
|
||||
: _hash (0)
|
||||
, _count (0)
|
||||
, _string(name)
|
||||
{
|
||||
if (!_SHARED_NAME_MAP) _SHARED_NAME_MAP = new SharedNameMap();
|
||||
(*_SHARED_NAME_MAP)[&_string] = this;
|
||||
|
||||
if (_idCounter == std::numeric_limits<unsigned int>::max()) {
|
||||
throw Error( "SharedName::SharedName(): Identifier counter has reached it's limit (%d bits)."
|
||||
, std::numeric_limits<unsigned int>::digits );
|
||||
}
|
||||
for ( char c : _string ) _hash = 131 * _hash + int(c);
|
||||
|
||||
// if (_idCounter == std::numeric_limits<unsigned long>::max()) {
|
||||
// throw Error( "SharedName::SharedName(): Identifier counter has reached it's limit (%d bits)."
|
||||
// , std::numeric_limits<unsigned long>::digits );
|
||||
// }
|
||||
cdebug_log(0,0) << "SharedName::SharedName() hash:" << _hash << " \"" << _string << "\"" << endl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,7 +71,7 @@ void SharedName::release()
|
|||
string SharedName::_getString() const
|
||||
// **********************************
|
||||
{
|
||||
return "<" + _TName("SharedName") + " " + getString(_count) + " id:" + getString(_id) + " " + _string + ">";
|
||||
return "<" + _TName("SharedName") + " " + getString(_count) + " hash:" + getString(_hash) + " " + _string + ">";
|
||||
}
|
||||
|
||||
Record* SharedName::_getRecord() const
|
||||
|
|
|
@ -98,22 +98,15 @@ class SharedPath_Instances : public Collection<Instance*> {
|
|||
// ****************************************************************************************************
|
||||
|
||||
static char NAME_SEPARATOR = '.';
|
||||
unsigned int SharedPath::_idCounter = 0;
|
||||
|
||||
|
||||
SharedPath::SharedPath(Instance* headInstance, SharedPath* tailSharedPath)
|
||||
// ***********************************************************************
|
||||
: _id(_idCounter++),
|
||||
_headInstance(headInstance),
|
||||
: _headInstance(headInstance),
|
||||
_tailSharedPath(tailSharedPath),
|
||||
_quarkMap(),
|
||||
_nextOfInstanceSharedPathMap(NULL)
|
||||
{
|
||||
if (_idCounter == std::numeric_limits<unsigned int>::max()) {
|
||||
throw Error( "SharedName::SharedName(): Identifier counter has reached it's limit (%d bits)."
|
||||
, std::numeric_limits<unsigned int>::digits );
|
||||
}
|
||||
|
||||
if (!_headInstance)
|
||||
throw Error("Can't create " + _TName("SharedPath") + " : null head instance");
|
||||
|
||||
|
@ -134,6 +127,8 @@ SharedPath::SharedPath(Instance* headInstance, SharedPath* tailSharedPath)
|
|||
);
|
||||
|
||||
_headInstance->_getSharedPathMap()._insert(this);
|
||||
|
||||
cdebug_log(0,0) << "SharedPath::SharedPath() pathHash:" << getHash() << " \"" << this << "\"" << endl;
|
||||
}
|
||||
|
||||
SharedPath::~SharedPath()
|
||||
|
@ -190,6 +185,10 @@ string SharedPath::getName() const
|
|||
return name;
|
||||
}
|
||||
|
||||
unsigned long SharedPath::getHash() const
|
||||
// ***************************************
|
||||
{ return (_headInstance->getId() << 1) + ((_tailSharedPath) ? _tailSharedPath->getHash() << 1: 0); }
|
||||
|
||||
string SharedPath::getJsonString(unsigned long flags) const
|
||||
// ********************************************************
|
||||
{
|
||||
|
|
|
@ -738,7 +738,7 @@ namespace Hurricane {
|
|||
|
||||
|
||||
unsigned Technology::LayerMap::_getHashValue ( Name name ) const
|
||||
{ return name._getSharedName()->getId() / 8; }
|
||||
{ return name._getSharedName()->getHash() / 8; }
|
||||
|
||||
|
||||
Layer* Technology::LayerMap::_getNextElement ( Layer* layer ) const
|
||||
|
|
|
@ -33,18 +33,18 @@ namespace Hurricane {
|
|||
friend class Name;
|
||||
|
||||
public:
|
||||
inline unsigned int getId () const;
|
||||
const string& _getSString () const { return _string; };
|
||||
string _getTypeName () const { return _TName("SharedName"); };
|
||||
string _getString () const;
|
||||
Record* _getRecord () const;
|
||||
private:
|
||||
SharedName ( const string& );
|
||||
SharedName ( const SharedName& );
|
||||
~SharedName ();
|
||||
SharedName& operator= ( const SharedName& );
|
||||
void capture ();
|
||||
void release ();
|
||||
inline unsigned long getHash () const;
|
||||
const string& _getSString () const { return _string; };
|
||||
string _getTypeName () const { return _TName("SharedName"); };
|
||||
string _getString () const;
|
||||
Record* _getRecord () const;
|
||||
private:
|
||||
SharedName ( const string& );
|
||||
SharedName ( const SharedName& );
|
||||
~SharedName ();
|
||||
SharedName& operator= ( const SharedName& );
|
||||
void capture ();
|
||||
void release ();
|
||||
|
||||
private:
|
||||
struct SharedNameMapComparator {
|
||||
|
@ -54,14 +54,13 @@ namespace Hurricane {
|
|||
|
||||
private:
|
||||
static SharedNameMap* _SHARED_NAME_MAP;
|
||||
static unsigned int _idCounter;
|
||||
unsigned int _id;
|
||||
unsigned long _hash;
|
||||
int _count;
|
||||
string _string;
|
||||
};
|
||||
|
||||
|
||||
inline unsigned int SharedName::getId () const { return _id; }
|
||||
inline unsigned long SharedName::getHash () const { return _hash; }
|
||||
|
||||
|
||||
} // End of Hurricane namespace.
|
||||
|
|
|
@ -60,8 +60,6 @@ class SharedPath {
|
|||
// Attributes
|
||||
// **********
|
||||
|
||||
private: static unsigned int _idCounter;
|
||||
private: unsigned int _id;
|
||||
private: Instance* _headInstance;
|
||||
private: SharedPath* _tailSharedPath;
|
||||
private: QuarkMap _quarkMap;
|
||||
|
@ -91,7 +89,7 @@ class SharedPath {
|
|||
|
||||
public: static char getNameSeparator();
|
||||
|
||||
public: unsigned int getId() const { return _id; }
|
||||
public: unsigned long getHash() const;
|
||||
public: Instance* getHeadInstance() const {return _headInstance;};
|
||||
public: SharedPath* getTailSharedPath() const {return _tailSharedPath;};
|
||||
public: SharedPath* getHeadSharedPath() const;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// | Author : Sophie BELLOEIL |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./PyCell.cpp" |
|
||||
// | C++ Module : "./PyVertical.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
katana/TrackElement.h katana/TrackElements.h
|
||||
katana/TrackSegment.h
|
||||
katana/TrackSegmentRegular.h
|
||||
katana/TrackSegmentNonPref.h
|
||||
katana/TrackSegmentWide.h
|
||||
katana/TrackFixedSegment.h
|
||||
katana/TrackMarker.h
|
||||
|
@ -53,6 +54,7 @@
|
|||
TrackElements.cpp
|
||||
TrackSegment.cpp
|
||||
TrackSegmentRegular.cpp
|
||||
TrackSegmentNonPref.cpp
|
||||
TrackSegmentWide.cpp
|
||||
TrackFixedSegment.cpp
|
||||
TrackMarker.cpp
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace Katana {
|
|||
cout << Dots::asUInt (" - Global router H reserved local" ,_hTracksReservedLocal) << endl;
|
||||
cout << Dots::asUInt (" - Global router V reserved local" ,_vTracksReservedLocal) << endl;
|
||||
cout << Dots::asULong(" - Events limit (iterations)" ,_eventsLimit) << endl;
|
||||
cout << Dots::asUInt (" - Ripup limit, straps" ,_ripupLimits[StrapRipupLimit]) << endl;
|
||||
cout << Dots::asUInt (" - Ripup limit, straps & unbreakables" ,_ripupLimits[StrapRipupLimit]) << endl;
|
||||
cout << Dots::asUInt (" - Ripup limit, locals" ,_ripupLimits[LocalRipupLimit]) << endl;
|
||||
cout << Dots::asUInt (" - Ripup limit, globals" ,_ripupLimits[GlobalRipupLimit]) << endl;
|
||||
cout << Dots::asUInt (" - Ripup limit, long globals" ,_ripupLimits[LongGlobalRipupLimit]) << endl;
|
||||
|
@ -183,10 +183,10 @@ namespace Katana {
|
|||
record->add ( getSlot("_ripupCost" ,_ripupCost ) );
|
||||
record->add ( getSlot("_eventsLimit" ,_eventsLimit ) );
|
||||
|
||||
record->add ( getSlot("_ripupLimits[StrapRipupLimit]" ,_ripupLimits[StrapRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[LocalRipupLimit]" ,_ripupLimits[LocalRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[GlobalRipupLimit]" ,_ripupLimits[GlobalRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[LongGlobalRipupLimit]",_ripupLimits[LongGlobalRipupLimit]) );
|
||||
record->add ( getSlot("_ripupLimits[StrapRipupLimit]" ,_ripupLimits[StrapRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[LocalRipupLimit]" ,_ripupLimits[LocalRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[GlobalRipupLimit]" ,_ripupLimits[GlobalRipupLimit] ) );
|
||||
record->add ( getSlot("_ripupLimits[LongGlobalRipupLimit]" ,_ripupLimits[LongGlobalRipupLimit]) );
|
||||
|
||||
// for ( size_t i=0 ; i<MaxMetalDepth ; ++i ) {
|
||||
// ostringstream paramName;
|
||||
|
|
|
@ -143,7 +143,40 @@ namespace Katana {
|
|||
cdebug_log(159,0) << "Canonical // interval: " << interval << endl;
|
||||
|
||||
_perpandiculars.push_back( perpandicular );
|
||||
if (perpandicular->getTrack()) {
|
||||
|
||||
if (perpandicular->isNonPref()) {
|
||||
AutoContact* source = perpandicular->base()->getAutoSource();
|
||||
AutoContact* target = perpandicular->base()->getAutoTarget();
|
||||
DbU::Unit pitch = Session::getPitch ( perpandicular->getLayer() );
|
||||
Flags direction = Session::getDirection( perpandicular->getLayer() );
|
||||
Interval trackFree ( false );
|
||||
|
||||
if (source->canDrag()) {
|
||||
if (direction & Flags::Horizontal)
|
||||
trackFree.intersection( source->getCBYMin(), source->getCBYMax() );
|
||||
else
|
||||
trackFree.intersection( source->getCBXMin(), source->getCBXMax() );
|
||||
cdebug_log(159,0) << "trackFree (source drag): " << trackFree << endl;
|
||||
}
|
||||
if (target->canDrag()) {
|
||||
if (direction & Flags::Horizontal)
|
||||
trackFree.intersection( target->getCBYMin(), target->getCBYMax() );
|
||||
else
|
||||
trackFree.intersection( target->getCBXMin(), target->getCBXMax() );
|
||||
cdebug_log(159,0) << "trackFree (target drag): " << trackFree << endl;
|
||||
}
|
||||
|
||||
if (not source->canDrag() and not target->canDrag())
|
||||
perpandicular->base()->getCanonical( trackFree );
|
||||
|
||||
trackFree.inflate( 1*pitch, 1*pitch );
|
||||
cdebug_log(159,0) << "Non-Pref Track Perpandicular Free: " << trackFree << endl;
|
||||
|
||||
//_perpandicularFree.intersection
|
||||
// ( trackFree.inflate ( pitch - perpandicular->getExtensionCap(Flags::Source)
|
||||
// , pitch - perpandicular->getExtensionCap(Flags::Target)) );
|
||||
_perpandicularFree.intersection( trackFree );
|
||||
} else if (perpandicular->getTrack()) {
|
||||
Interval trackFree = perpandicular->getFreeInterval();
|
||||
cdebug_log(159,0) << "Track Perpandicular Free: " << trackFree << endl;
|
||||
|
||||
|
|
|
@ -63,11 +63,16 @@ namespace {
|
|||
inline void DigitalDistance::setNet ( Net* net ) { _net = net; }
|
||||
|
||||
|
||||
DbU::Unit DigitalDistance::operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const
|
||||
DbU::Unit DigitalDistance::operator() ( const Vertex* source, const Vertex* target, const Edge* edge ) const
|
||||
{
|
||||
if (source->getGCell()->isStdCellRow() and target->getGCell()->isStdCellRow())
|
||||
return Vertex::unreachable;
|
||||
|
||||
if ( source->getGCell()->isGoStraight()
|
||||
and source->getFrom()
|
||||
and (source->getFrom()->isHorizontal() xor edge->isHorizontal()))
|
||||
return Vertex::unreachable;
|
||||
|
||||
if (edge->getCapacity() <= 0) {
|
||||
if (target->getGCell()->isStdCellRow()
|
||||
and target->hasValidStamp() and (target->getConnexId() >= 0) )
|
||||
|
@ -117,7 +122,8 @@ namespace {
|
|||
<< DbU::getValueString(source->getDistance()) << " + ("
|
||||
<< congestionCost << " + "
|
||||
<< viaCost << " + "
|
||||
<< edge->getHistoricCost() << ") * "
|
||||
//<< edge->getHistoricCost() << ") * "
|
||||
<< historicCost << ") * "
|
||||
<< DbU::getValueString(edgeDistance) << " * "
|
||||
<< hvScaling
|
||||
<< endl;
|
||||
|
@ -312,12 +318,12 @@ namespace Katana {
|
|||
openSession();
|
||||
|
||||
annotateGlobalGraph();
|
||||
for ( NetData* netData : getNetOrdering() ) {
|
||||
if (netData->isGlobalRouted() or netData->isExcluded()) continue;
|
||||
// for ( NetData* netData : getNetOrdering() ) {
|
||||
// if (netData->isGlobalRouted() or netData->isExcluded()) continue;
|
||||
|
||||
updateEstimateDensity( netData, 1.0 );
|
||||
netData->setGlobalEstimated( true );
|
||||
}
|
||||
// updateEstimateDensity( netData, 1.0 );
|
||||
// netData->setGlobalEstimated( true );
|
||||
// }
|
||||
|
||||
// Session::close();
|
||||
// Breakpoint::stop( 1, "After global routing estimation." );
|
||||
|
@ -339,9 +345,12 @@ namespace Katana {
|
|||
|
||||
if (isChannelMode())
|
||||
dijkstra->setSearchAreaHalo( Session::getSliceHeight()*10 );
|
||||
else
|
||||
dijkstra->setSearchAreaHalo( Session::getSliceHeight()*1 );
|
||||
|
||||
size_t iteration = 0;
|
||||
size_t netCount = 0;
|
||||
bool globalEstimated = false;
|
||||
size_t iteration = 0;
|
||||
size_t netCount = 0;
|
||||
do {
|
||||
cmess2 << " [" << setfill(' ') << setw(3) << iteration << "] nets:";
|
||||
|
||||
|
@ -359,7 +368,24 @@ namespace Katana {
|
|||
distance->setNet( netData->getNet() );
|
||||
dijkstra->load( netData->getNet() );
|
||||
dijkstra->run();
|
||||
netData->setGlobalRouted( true );
|
||||
++netCount;
|
||||
|
||||
// if (netData->getNet()->getName() == Name("mips_r3000_1m_dp_shift32_rshift_se_msb")) {
|
||||
// Session::close();
|
||||
// Breakpoint::stop( 1, "After global routing of \"mips_r3000_1m_dp_shift32_rshift_se_msb\"." );
|
||||
// openSession();
|
||||
// }
|
||||
|
||||
if ( (netData->getRpCount() < 11) and not globalEstimated ) {
|
||||
for ( NetData* netData2 : getNetOrdering() ) {
|
||||
if (netData2->isGlobalRouted() or netData2->isExcluded()) continue;
|
||||
|
||||
updateEstimateDensity( netData2, 1.0 );
|
||||
netData2->setGlobalEstimated( true );
|
||||
}
|
||||
globalEstimated = true;
|
||||
}
|
||||
}
|
||||
cmess2 << left << setw(6) << netCount;
|
||||
|
||||
|
@ -416,9 +442,11 @@ namespace Katana {
|
|||
|
||||
cerr << " o Global routing did not complete, overflowed edges:" << endl;
|
||||
for ( size_t iEdge = 0 ; iEdge<ovEdges.size() ; ++iEdge ) {
|
||||
cerr << " " << dec << setw(4) << (iEdge+1) << "| " << ovEdges[iEdge] << endl;
|
||||
for ( Segment* segment : ovEdges[iEdge]->getSegments() )
|
||||
cerr << " " << dec << setw(4) << (iEdge+1) << "+ " << ovEdges[iEdge] << endl;
|
||||
for ( Segment* segment : ovEdges[iEdge]->getSegments() ) {
|
||||
cerr << " | " << segment << " " << DbU::getValueString(segment->getLength()) << endl;
|
||||
nets.insert( segment->getNet() );
|
||||
}
|
||||
}
|
||||
|
||||
cerr << " o Conflicting nets:" << endl;
|
||||
|
@ -466,7 +494,7 @@ namespace Katana {
|
|||
} else {
|
||||
if (component->getLayer() == cLayer) {
|
||||
Contact* contact = static_cast<Contact*>( component );
|
||||
size_t gslaves = 0;
|
||||
//size_t gslaves = 0;
|
||||
|
||||
for ( Component* slave : contact->getSlaveComponents().getSubSet<Segment*>() ) {
|
||||
if (slave->getLayer() == vLayer) { ++viaCount; break; }
|
||||
|
|
|
@ -243,6 +243,8 @@ namespace Katana {
|
|||
{
|
||||
KatanaEngine* katana = getForFramework( CreateEngine );
|
||||
katana->runGlobalRouter();
|
||||
|
||||
//Breakpoint::stop( 0, "GraphicKatanaEngine::_globalRoute() done." );
|
||||
}
|
||||
|
||||
|
||||
|
@ -252,6 +254,8 @@ namespace Katana {
|
|||
|
||||
_viewer->clearToolInterrupt();
|
||||
katana->loadGlobalRouting( Anabatic::EngineLoadGrByNet );
|
||||
|
||||
//Breakpoint::stop( 0, "GraphicKatanaEngine::_loadGlobalRouting() done." );
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,6 +264,8 @@ namespace Katana {
|
|||
KatanaEngine* katana = getForFramework( NoFlags );
|
||||
//katana->balanceGlobalDensity();
|
||||
katana->layerAssign( Anabatic::EngineNoNetLayerAssign );
|
||||
|
||||
//Breakpoint::stop( 0, "GraphicKatanaEngine::_balanceGlobalDensity() done." );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -354,9 +354,10 @@ namespace Katana {
|
|||
{
|
||||
if (segment->isBlockage()) return 0;
|
||||
|
||||
if (segment->isStrap ()) return _configuration->getRipupLimit( Configuration::StrapRipupLimit );
|
||||
if (segment->isShortNet()) return _configuration->getRipupLimit( Configuration::ShortNetRipupLimit );
|
||||
if (segment->isGlobal()) {
|
||||
if (segment->isStrap ()) return _configuration->getRipupLimit( Configuration::StrapRipupLimit );
|
||||
if (segment->isUnbreakable()) return _configuration->getRipupLimit( Configuration::StrapRipupLimit );
|
||||
if (segment->isShortNet ()) return _configuration->getRipupLimit( Configuration::ShortNetRipupLimit );
|
||||
if (segment->isGlobal ()) {
|
||||
vector<GCell*> gcells;
|
||||
segment->getGCells( gcells );
|
||||
if (gcells.size() > 2)
|
||||
|
@ -519,7 +520,6 @@ namespace Katana {
|
|||
|
||||
_negociateWindow = NegociateWindow::create( this );
|
||||
_negociateWindow->setGCells( getGCells() );
|
||||
_computeCagedConstraints();
|
||||
_negociateWindow->run( flags );
|
||||
_negociateWindow->destroy();
|
||||
_negociateWindow = NULL;
|
||||
|
|
|
@ -150,6 +150,14 @@ namespace Katana {
|
|||
if (_data == NULL) { cdebug_tabw(159,-1); return true; }
|
||||
|
||||
_fsm.addAction( _segment, type, axisHint );
|
||||
if (_segment->isDrag()) {
|
||||
set<TrackElement*> canonicals;
|
||||
for ( TrackElement* perpand
|
||||
: _segment->getPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) {
|
||||
if (not _fsm.hasAction(perpand))
|
||||
Manipulator(perpand,_fsm).ripup( SegmentAction::OtherRipup|SegmentAction::EventLevel1 );
|
||||
}
|
||||
}
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
@ -602,7 +610,7 @@ namespace Katana {
|
|||
TrackElement* segment = Session::lookup(doglegs[i]);
|
||||
if (not segment->getTrack() and track) {
|
||||
cdebug_log(159,0) << "Direct Track insert of: " << segment << endl;
|
||||
Session::addInsertEvent( segment, track );
|
||||
Session::addInsertEvent( segment, track, track->getAxis() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -650,7 +658,7 @@ namespace Katana {
|
|||
|
||||
bool Manipulator::insertInTrack ( size_t icost )
|
||||
{
|
||||
cdebug_log(159,1) << "Manipulator::insertInTrack(size_t)" << endl;
|
||||
cdebug_log(159,1) << "Manipulator::insertInTrack(icost)" << endl;
|
||||
cdebug_log(159,0) << _segment << endl;
|
||||
|
||||
bool success = true;
|
||||
|
@ -665,7 +673,7 @@ namespace Katana {
|
|||
_fsm.setState ( SegmentFsm::OtherRipup );
|
||||
_fsm.addAction( _segment
|
||||
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis|SegmentAction::EventLevel4
|
||||
, _fsm.getTrack1(icost)->getAxis() );
|
||||
, _fsm.getCandidateAxis1(icost) );
|
||||
|
||||
#if THIS_IS_DISABLED
|
||||
uint32_t flags = 0;
|
||||
|
@ -697,7 +705,7 @@ namespace Katana {
|
|||
//bool rightIntrication = false;
|
||||
bool success = true;
|
||||
|
||||
cdebug_log(159,1) << "Manipulator::_insertInTrack(size_t) - " << toFree << endl;
|
||||
cdebug_log(159,1) << "Manipulator::_insertInTrack(icost,itrack) - " << toFree << endl;
|
||||
cdebug_log(159,0) << _segment << endl;
|
||||
|
||||
for ( size_t i = begin ; success and (i < end) ; i++ ) {
|
||||
|
@ -774,7 +782,8 @@ namespace Katana {
|
|||
}
|
||||
|
||||
cdebug_log(159,0) << "- Hard overlap/enclosure/shrink " << segment2 << endl;
|
||||
if ( _segment->isStrap() and segment2->isGlobal() ) continue;
|
||||
//if ( (_segment->isUnbreakable() or _segment->isStrap()) and segment2->isGlobal() ) continue;
|
||||
if ( (_segment->isStrap()) and segment2->isGlobal() ) continue;
|
||||
if ( not (success = Manipulator(segment2,_fsm).ripup(SegmentAction::OtherRipup)) )
|
||||
continue;
|
||||
|
||||
|
@ -782,27 +791,27 @@ namespace Katana {
|
|||
for( TrackElement* segment3
|
||||
: segment2->getPerpandiculars().getSubSet(TrackElements_UniqCanonical(canonicals)) ) {
|
||||
DataNegociate* data3 = segment3->getDataNegociate();
|
||||
if ( not data3 ) continue;
|
||||
if (not data3) continue;
|
||||
|
||||
RoutingEvent* event3 = data3->getRoutingEvent();
|
||||
if ( not event3 ) continue;
|
||||
if (not event3) continue;
|
||||
|
||||
if ( not toFree.intersect(event3->getConstraints()) ) {
|
||||
if (not toFree.intersect(event3->getConstraints())) {
|
||||
cdebug_log(159,0) << " . " << segment3 << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << " | " << segment3 << endl;
|
||||
|
||||
if ( shrinkRight xor shrinkLeft ) {
|
||||
if ( shrinkRight ) {
|
||||
if (shrinkRight xor shrinkLeft) {
|
||||
if (shrinkRight) {
|
||||
if ( not (success=Manipulator(segment3,_fsm)
|
||||
.ripup( SegmentAction::OtherRipupPerpandAndPushAside
|
||||
, toFree.getVMin() - getPPitch()/2
|
||||
)) )
|
||||
break;
|
||||
|
||||
if ( event3->getTracksFree() == 1 ) {
|
||||
if (event3->getTracksFree() == 1) {
|
||||
cdebug_log(159,0) << "Potential left intrication with other perpandicular." << endl;
|
||||
if ( segment3->getAxis() == segment2->getTargetAxis() ) {
|
||||
//leftIntrication = true;
|
||||
|
@ -810,7 +819,7 @@ namespace Katana {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( shrinkLeft ) {
|
||||
if (shrinkLeft) {
|
||||
cdebug_log(159,0) << "Move PP to right: "
|
||||
<< DbU::getValueString(toFree.getVMax()) << " + "
|
||||
<< DbU::getValueString(getPPitch()/2)
|
||||
|
@ -820,7 +829,7 @@ namespace Katana {
|
|||
, toFree.getVMax() + getPPitch()/2
|
||||
)) )
|
||||
break;
|
||||
if ( event3->getTracksFree() == 1 ) {
|
||||
if (event3->getTracksFree() == 1) {
|
||||
cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl;
|
||||
if ( segment3->getAxis() == segment2->getSourceAxis() ) {
|
||||
//rightIntrication = true;
|
||||
|
@ -830,6 +839,7 @@ namespace Katana {
|
|||
}
|
||||
} else {
|
||||
if ( not (success=Manipulator(segment3,_fsm).ripup( SegmentAction::OtherRipup
|
||||
| SegmentAction::DecreaseRipup
|
||||
| SegmentAction::EventLevel3 )) )
|
||||
break;
|
||||
}
|
||||
|
@ -856,7 +866,7 @@ namespace Katana {
|
|||
_fsm.setState ( SegmentFsm::OtherRipup );
|
||||
_fsm.addAction( _segment
|
||||
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis
|
||||
, _fsm.getTrack(icost)->getAxis() );
|
||||
, _fsm.getCandidateAxis1(icost) );
|
||||
} else
|
||||
_fsm.clearActions();
|
||||
|
||||
|
@ -1057,7 +1067,7 @@ namespace Katana {
|
|||
_fsm.setState ( SegmentFsm::OtherRipup );
|
||||
_fsm.addAction( _segment
|
||||
, SegmentAction::SelfInsert|SegmentAction::MoveToAxis
|
||||
, _fsm.getTrack(itrack)->getAxis()
|
||||
, _fsm.getCandidateAxis1(itrack)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1091,7 +1101,7 @@ namespace Katana {
|
|||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_segment->getLayer());
|
||||
|
||||
cdebug_tabw(159,1);
|
||||
for( Track* track : Tracks_Range::get(plane,uside)) {
|
||||
for ( Track* track : Tracks_Range::get(plane,uside)) {
|
||||
size_t begin;
|
||||
size_t end;
|
||||
|
||||
|
@ -1175,7 +1185,7 @@ namespace Katana {
|
|||
} else {
|
||||
if (_segment->getLength() < 20*getPitch()) {
|
||||
if (not (flags & AllowShortPivotUp)) return false;
|
||||
if (not _segment->canPivotUp(1.0,kflags)) return false;
|
||||
if (not _segment->canPivotUp(1.0,(kflags & ~Flags::IgnoreContacts))) return false;
|
||||
}
|
||||
if (not _segment->canMoveUp(0.5,kflags)) return false;
|
||||
}
|
||||
|
@ -1299,6 +1309,7 @@ namespace Katana {
|
|||
|
||||
if (_segment->isFixed()) return false;
|
||||
if (not _event->canMinimize()) return false;
|
||||
if (_segment->isNonPref()) return true;
|
||||
|
||||
DbU::Unit minSpan = DbU::Max;
|
||||
DbU::Unit maxSpan = DbU::Min;
|
||||
|
@ -1307,7 +1318,7 @@ namespace Katana {
|
|||
if (_segment->base()->getAutoSource()->getAnchor()) {
|
||||
cdebug_log(159,0) << " | " << _segment->base()->getAutoSource() << endl;
|
||||
Interval constraints ( _segment->base()->getAutoSource()->getUConstraints
|
||||
(perpandicularTo(_segment->getDirection())) );
|
||||
(_segment->getDirection()) );
|
||||
cdebug_log(159,0) << " | Constraints: " << constraints << endl;
|
||||
|
||||
minSpan = min( minSpan, constraints.getVMax() );
|
||||
|
@ -1318,7 +1329,7 @@ namespace Katana {
|
|||
if (_segment->base()->getAutoTarget()->getAnchor()) {
|
||||
cdebug_log(159,0) << " | " << _segment->base()->getAutoTarget() << endl;
|
||||
Interval constraints ( _segment->base()->getAutoTarget()->getUConstraints
|
||||
(perpandicularTo(_segment->getDirection())) );
|
||||
(_segment->getDirection()) );
|
||||
cdebug_log(159,0) << " | Constraints: " << constraints << endl;
|
||||
|
||||
minSpan = min( minSpan, constraints.getVMax() );
|
||||
|
@ -1587,9 +1598,17 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void Manipulator::repackPerpandiculars ()
|
||||
void Manipulator::repackPerpandiculars ( uint32_t flags )
|
||||
{
|
||||
cdebug_log(159,0) << "Manipulator::repackPerpandiculars()" << endl;
|
||||
cdebug_log(159,1) << "Manipulator::repackPerpandiculars()" << endl;
|
||||
|
||||
uint32_t parallelActionFlags = SegmentAction::SelfRipup|SegmentAction::EventLevel4;
|
||||
uint32_t perpandicularActionFlags = SegmentAction::SelfRipupPerpand;
|
||||
|
||||
if (flags & Manipulator::PerpandicularsFirst) {
|
||||
parallelActionFlags &= ~SegmentAction::EventLevel4;
|
||||
perpandicularActionFlags |= SegmentAction::EventLevel4;
|
||||
}
|
||||
|
||||
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
|
||||
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
|
||||
|
@ -1597,17 +1616,24 @@ namespace Katana {
|
|||
DataNegociate* data = perpandicular->getDataNegociate();
|
||||
|
||||
if (perpandicular->isFixed ()) continue;
|
||||
if (perpandicular->isGlobal()) continue;
|
||||
//if (perpandicular->isGlobal()) continue;
|
||||
if (not data) continue;
|
||||
if (data->getState() >= DataNegociate::RepairFailed) continue;
|
||||
|
||||
if (RoutingEvent::getStage() == RoutingEvent::Repair) {
|
||||
if (_segment->getDataNegociate()->getState() < DataNegociate::Repair)
|
||||
_segment->getDataNegociate()->resetRipupCount();
|
||||
|
||||
data->setState( DataNegociate::Repair );
|
||||
if (data->getStateCount() > 1) data->resetStateCount();
|
||||
}
|
||||
_fsm.addAction( perpandicular, SegmentAction::SelfRipupPerpand );
|
||||
|
||||
cdebug_log(159,0) << "Perpandicular ripup: " << perpandicular << endl;
|
||||
_fsm.addAction( perpandicular, perpandicularActionFlags );
|
||||
}
|
||||
_fsm.addAction( _segment, SegmentAction::SelfRipup|SegmentAction::EventLevel4 );
|
||||
_fsm.addAction( _segment, parallelActionFlags );
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Bug.h"
|
||||
|
@ -73,7 +74,10 @@ namespace {
|
|||
if (not intersect.contains(cost.getInterval()))
|
||||
intersect.intersection( cost.getInterval() );
|
||||
else {
|
||||
cost.setLonguestOverlap( intersect.getSize() );
|
||||
DbU::Unit beginOverlap = cost.getInterval().getVMin() - intersect.getVMin();
|
||||
DbU::Unit endOverlap = intersect.getVMax() - cost.getInterval().getVMax();
|
||||
|
||||
cost.setLonguestOverlap( std::min( beginOverlap, endOverlap ) );
|
||||
cost.setGlobalEnclosed();
|
||||
}
|
||||
|
||||
|
@ -85,6 +89,7 @@ namespace {
|
|||
cost.mergeDataState( data->getState() );
|
||||
if (data->getState() >= DataNegociate::LocalVsGlobal) {
|
||||
cdebug_log(159,0) << "MaximumSlack/LocalVsGlobal for " << segment << endl;
|
||||
cost.setAtRipupLimit();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +115,27 @@ namespace {
|
|||
|
||||
cdebug_log(159,0) << "| Increment Delta: " << DbU::getValueString(intersect.getSize()) << endl;
|
||||
cost.incDelta( intersect.getSize() );
|
||||
|
||||
// if (segment->base()->getId() == 70433) {
|
||||
// cdebug_log(159,0) << "| G:" << cost.isForGlobal()
|
||||
// << " L:" << segment->isLocal()
|
||||
// << " rpD:" << segment->base()->getRpDistance()
|
||||
// << " state:" << data->getState()
|
||||
// << " (Dogleg:" << DataNegociate::Dogleg
|
||||
// << ") ripup:" << data->getRipupCount()
|
||||
// << endl;
|
||||
// }
|
||||
|
||||
if ( cost.isForGlobal()
|
||||
and segment->isLocal()
|
||||
and (segment->base()->getRpDistance() < 2)
|
||||
and (data->getState() >= DataNegociate::Dogleg)
|
||||
//and (data->getRipupCount() > Session::getConfiguration()->getRipupLimit(Configuration::LocalRipupLimit) - 2)
|
||||
) {
|
||||
cost.setInfinite();
|
||||
cdebug_log(159,0) << "Infinite cost from (RP access)" << segment << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -183,6 +209,7 @@ namespace Katana {
|
|||
using std::left;
|
||||
using std::right;
|
||||
using std::setprecision;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::tab;
|
||||
|
@ -317,6 +344,13 @@ namespace Katana {
|
|||
if (created) {
|
||||
cdebug_log(159,0) << "* " << trackSegment << endl;
|
||||
|
||||
if (trackSegment->isNonPref()) {
|
||||
_segments.push_back( trackSegment );
|
||||
cdebug_log(159,0) << "Non-preferred diection, do not attempt to set on track." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return trackSegment;
|
||||
}
|
||||
|
||||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
|
||||
Track* track = plane->getTrackByPosition ( autoSegment->getAxis() );
|
||||
Interval uside = autoSegment->getAutoSource()->getGCell()->getSide( perpandicularTo(autoSegment->getDirection()) );
|
||||
|
@ -347,7 +381,7 @@ namespace Katana {
|
|||
trackSegment->invalidate();
|
||||
|
||||
if (trackSegment->isFixed()) {
|
||||
Session::addInsertEvent( trackSegment, track );
|
||||
Session::addInsertEvent( trackSegment, track, track->getAxis() );
|
||||
} else {
|
||||
_segments.push_back( trackSegment );
|
||||
}
|
||||
|
@ -512,7 +546,7 @@ namespace Katana {
|
|||
ofprofile << setw(10) << right << count << " ";
|
||||
for ( size_t i=0 ; i<6 ; ++i ) {
|
||||
if (i == depth)
|
||||
ofprofile << setw(10) << right << setprecision(2) << event->getPriority () << " ";
|
||||
ofprofile << setw(10) << right << setprecision(2) << event->getPriority() << " ";
|
||||
else
|
||||
ofprofile << setw(10) << right << setprecision(2) << 0.0 << " ";
|
||||
}
|
||||
|
@ -531,12 +565,16 @@ namespace Katana {
|
|||
} else {
|
||||
cmess2 << " <event:" << right << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
|
||||
<< event->getEventLevel() << ":" << event->getPriority() << "> "
|
||||
<< event->getEventLevel() << ":" << event->getPriority()
|
||||
<< ":" << DbU::getValueString(event->getSegment()->getLength()) << "> "
|
||||
<< event->getSegment()
|
||||
<< endl;
|
||||
cmess2.flush();
|
||||
}
|
||||
|
||||
//if (RoutingEvent::getProcesseds() == 14473)
|
||||
// Breakpoint::stop( 0, "Before processing RoutingEvent 14473." );
|
||||
|
||||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
count++;
|
||||
|
||||
|
@ -630,6 +668,7 @@ namespace Katana {
|
|||
|
||||
if (not (flags & Flags::PreRoutedStage)) {
|
||||
_katana->preProcess();
|
||||
_katana->_computeCagedConstraints();
|
||||
Session::revalidate();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "hurricane/Technology.h"
|
||||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/RegularLayer.h"
|
||||
#include "hurricane/Pad.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
|
@ -52,6 +53,7 @@ namespace {
|
|||
using Hurricane::Net;
|
||||
using Hurricane::DeepNet;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Pad;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::NetExternalComponents;
|
||||
|
@ -502,7 +504,8 @@ namespace {
|
|||
// - plane->getLayerGauge()->getHalfWireWidth()
|
||||
// - DbU::fromLambda(0.1);
|
||||
DbU::Unit delta = plane->getLayerGauge()->getObstacleDw() - DbU::fromLambda(0.1);
|
||||
DbU::Unit extension = layer->getExtentionCap() - plane->getLayerGauge()->getLayer()->getMinimalSpacing()/2;
|
||||
DbU::Unit extension = layer->getExtentionCap();
|
||||
//DbU::Unit extension = layer->getExtentionCap() - plane->getLayerGauge()->getLayer()->getMinimalSpacing()/2;
|
||||
//DbU::Unit extension = layer->getExtentionCap() - plane->getLayerGauge()->getHalfPitch() + getHalfWireWidth();
|
||||
//DbU::Unit extension = layer->getExtentionCap();
|
||||
//DbU::Unit extension = Session::getExtentionCap();
|
||||
|
@ -512,9 +515,9 @@ namespace {
|
|||
DbU::Unit axisMax = 0;
|
||||
|
||||
cdebug_log(159,0) << " delta:" << DbU::getValueString(delta)
|
||||
<< " (pitch:" << DbU::getValueString(plane->getLayerGauge()->getPitch())
|
||||
<< " , ww/2:" << DbU::getValueString(plane->getLayerGauge()->getHalfWireWidth())
|
||||
<< ")" << endl;
|
||||
<< " (pitch:" << DbU::getValueString(plane->getLayerGauge()->getPitch())
|
||||
<< " , ww/2:" << DbU::getValueString(plane->getLayerGauge()->getHalfWireWidth())
|
||||
<< ")" << endl;
|
||||
|
||||
// if ( type == Constant::PinOnly ) {
|
||||
// cdebug_log(159,0) << " Layer is PinOnly." << endl;
|
||||
|
@ -540,7 +543,7 @@ namespace {
|
|||
}
|
||||
|
||||
cdebug_log(159,0) << " chunk: [" << DbU::getValueString((*ichunk).getVMin())
|
||||
<< ":" << DbU::getValueString((*ichunk).getVMax()) << "]" << endl;
|
||||
<< ":" << DbU::getValueString((*ichunk).getVMax()) << "]" << endl;
|
||||
|
||||
segment = Horizontal::create ( net
|
||||
, layer
|
||||
|
@ -1076,6 +1079,19 @@ namespace {
|
|||
<< " " << basicLayer << endl;
|
||||
|
||||
_powerRailsPlanes.merge ( bb, rootNet );
|
||||
} else {
|
||||
const Pad* pad = dynamic_cast<const Pad*>(component);
|
||||
if (pad != NULL) {
|
||||
_goMatchCount++;
|
||||
|
||||
Box bb = pad->getBoundingBox( basicLayer );
|
||||
transformation.applyOn( bb );
|
||||
|
||||
cdebug_log(159,0) << " Merging PowerRail element: " << pad << " bb:" << bb
|
||||
<< " " << basicLayer << endl;
|
||||
|
||||
_powerRailsPlanes.merge( bb, rootNet );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,9 +120,9 @@ namespace {
|
|||
|
||||
void propagateCagedConstraints ( TrackElement* segment, set<TrackElement*>& faileds )
|
||||
{
|
||||
if (not segment->isFixed()) return;
|
||||
cdebug_log(159,0) << "propagateCagedConstraints(): " << segment << endl;
|
||||
|
||||
cdebug_log(159,0) << "Propagate caging: " << segment << endl;
|
||||
if (not segment->isFixed()) return;
|
||||
|
||||
Track* track = segment->getTrack();
|
||||
//Flags direction = Session::getRoutingGauge()->getLayerDirection(segment->getLayer());
|
||||
|
@ -208,7 +208,6 @@ namespace {
|
|||
Interval constraints ( minConstraint, maxConstraint );
|
||||
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
|
||||
cdebug_log(159,0) << "Caged: " << constraints << " " << perpandiculars[iperpand] << endl;
|
||||
cerr << "Caged: " << constraints << " " << perpandiculars[iperpand] << endl;
|
||||
perpandiculars[iperpand]->base()->mergeUserConstraints( constraints );
|
||||
if (perpandiculars[iperpand]->base()->getUserConstraints().isEmpty()) {
|
||||
cdebug_log(159,0) << "Cumulative caged constraints are too tight on " << perpandiculars[iperpand] << endl;
|
||||
|
@ -257,7 +256,7 @@ namespace {
|
|||
|
||||
Configuration* configuration = Session::getConfiguration();
|
||||
const Layer* metal2 = configuration->getRoutingLayer( 1 );
|
||||
const Layer* metal3 = configuration->getRoutingLayer( 2 );
|
||||
//const Layer* metal3 = configuration->getRoutingLayer( 2 );
|
||||
Net* neighborNet = NULL;
|
||||
RoutingPlane* metal3plane = track->getRoutingPlane()->getTop();
|
||||
|
||||
|
@ -282,12 +281,6 @@ namespace {
|
|||
if ( (segment->getSourceU() - freeInterval.getVMin() < ppitch*3)
|
||||
or (freeInterval.getVMax() - segment->getTargetU() < ppitch*3) ) {
|
||||
cparanoid << "[INFO] Caged terminal: " << segment << endl;
|
||||
if ( (segment->getLayer () != metal2)
|
||||
or (segment->getLength() >= ppitch)
|
||||
or (segment->getNet () == neighborNet) ) {
|
||||
neighborNet = segment->getNet();
|
||||
continue;
|
||||
}
|
||||
|
||||
Anabatic::AutoContact* support = NULL;
|
||||
Anabatic::AutoContact* turn = NULL;
|
||||
|
@ -299,6 +292,19 @@ namespace {
|
|||
turn = segment->base()->getAutoSource();
|
||||
}
|
||||
|
||||
DbU::Unit supportLength = support->getConstraintBox().getWidth();
|
||||
cdebug_log(159,0) << "Support length (rp): " << DbU::getValueString(supportLength) << endl;
|
||||
|
||||
if ( (segment->getLayer () != metal2)
|
||||
//or (segment->getLength() >= ppitch)
|
||||
or (supportLength >= ppitch)
|
||||
or (segment->getNet () == neighborNet) ) {
|
||||
neighborNet = segment->getNet();
|
||||
continue;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Protect " << segment << endl;
|
||||
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
|
||||
Track* metal3track = metal3plane->getTrackByPosition( rp->getSourcePosition().getX() );
|
||||
|
||||
|
@ -321,6 +327,7 @@ namespace {
|
|||
}
|
||||
lastMovedUp = segment->getSourceU();
|
||||
|
||||
#if NOT_NEEDED_AFTER_6502_OPTIM
|
||||
Anabatic::AutoContact* source
|
||||
= Anabatic::AutoContactTerminal::create( support->getGCell()
|
||||
, rp
|
||||
|
@ -342,6 +349,7 @@ namespace {
|
|||
AutoSegment* fixedSegment = AutoSegment::create( source, target, Flags::Vertical );
|
||||
fixedSegment->setFlags( AutoSegment::SegFixed );
|
||||
Session::getNegociateWindow()->createTrackSegment( fixedSegment, Flags::LoadingStage );
|
||||
#endif
|
||||
}
|
||||
|
||||
neighborNet = segment->getNet();
|
||||
|
@ -415,7 +423,6 @@ namespace Katana {
|
|||
}
|
||||
|
||||
//DebugSession::close();
|
||||
|
||||
Session::revalidate ();
|
||||
}
|
||||
|
||||
|
|
|
@ -99,9 +99,17 @@ namespace Katana {
|
|||
if ( (lhs._segFlags & AutoSegment::SegFixedAxis) and not (rhs._segFlags & AutoSegment::SegFixedAxis)) return false;
|
||||
if (not (lhs._segFlags & AutoSegment::SegFixedAxis) and (rhs._segFlags & AutoSegment::SegFixedAxis)) return true;
|
||||
|
||||
if (lhs._rpDistance > rhs._rpDistance) return true;
|
||||
if (lhs._rpDistance < rhs._rpDistance) return false;
|
||||
|
||||
if (lhs._layerDepth > rhs._layerDepth) return true;
|
||||
if (lhs._layerDepth < rhs._layerDepth) return false;
|
||||
|
||||
if (lhs._rpDistance == 0) {
|
||||
if (lhs._length > rhs._length) return true;
|
||||
if (lhs._length < rhs._length) return false;
|
||||
}
|
||||
|
||||
if (lhs._priority > rhs._priority) return false;
|
||||
if (lhs._priority < rhs._priority) return true;
|
||||
|
||||
|
@ -126,6 +134,7 @@ namespace Katana {
|
|||
|
||||
RoutingEvent::Key::Key ( const RoutingEvent* event )
|
||||
: _tracksNb (event->getTracksNb())
|
||||
, _rpDistance (event->getSegment()->base()->getRpDistance())
|
||||
, _priority (event->getPriority())
|
||||
, _eventLevel (event->getEventLevel())
|
||||
, _segFlags (event->getSegment()->base()->getFlags())
|
||||
|
@ -143,6 +152,7 @@ namespace Katana {
|
|||
if (not event) return;
|
||||
|
||||
_tracksNb = event->getTracksNb();
|
||||
_rpDistance = event->getSegment()->base()->getRpDistance();
|
||||
_priority = event->getPriority();
|
||||
_eventLevel = event->getEventLevel();
|
||||
_segFlags = event->getSegment()->base()->getFlags();
|
||||
|
@ -358,6 +368,8 @@ namespace Katana {
|
|||
|
||||
if (getStage() == Repair) {
|
||||
fork->setMode( RoutingEvent::Repair );
|
||||
if (_segment->getDataNegociate()->getState() < DataNegociate::Repair)
|
||||
_segment->getDataNegociate()->resetRipupCount();
|
||||
_segment->getDataNegociate()->setState( DataNegociate::Repair );
|
||||
} else if (getStage() == RoutingEvent::Pack) {
|
||||
fork->setMode( RoutingEvent::Pack );
|
||||
|
@ -587,10 +599,11 @@ namespace Katana {
|
|||
if (fsm.getState() == SegmentFsm::EmptyTrackList) return;
|
||||
if (fsm.isSymmetric()) return;
|
||||
|
||||
cdebug_tabw(159,1);
|
||||
for ( size_t i = 0 ; i < fsm.getCosts().size() ; i++ )
|
||||
cdebug_log(159,0) << "| " << fsm.getCost(i) << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
|
||||
cdebug_log(159,0) << "| Candidate Tracks:" << endl;
|
||||
size_t itrack = 0;
|
||||
for ( itrack = 0 ; itrack < fsm.getCosts().size() ; itrack++ )
|
||||
cdebug_log(159,0) << "| " << itrack << ":" << fsm.getCost(itrack) << endl;
|
||||
|
||||
if (fsm.getCosts().size() and fsm.getCost(0)->isFree()) {
|
||||
cdebug_log(159,0) << "Insert in free space." << endl;
|
||||
|
@ -602,8 +615,10 @@ namespace Katana {
|
|||
cdebug_log(159,0) << "| " << perpandicular << endl;
|
||||
fsm.addAction( perpandicular, SegmentAction::SelfInsert );
|
||||
DataNegociate* data = perpandicular->getDataNegociate();
|
||||
if (data and (data->getState() < DataNegociate::Repair))
|
||||
if (data and (data->getState() < DataNegociate::Repair)) {
|
||||
data->setState( DataNegociate::Repair );
|
||||
data->resetRipupCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
fsm.doActions();
|
||||
|
@ -611,16 +626,18 @@ namespace Katana {
|
|||
} else {
|
||||
switch ( fsm.getData()->getStateCount() ) {
|
||||
case 1:
|
||||
// First try: minimize.
|
||||
Manipulator(_segment,fsm).minimize();
|
||||
fsm.addAction( _segment, SegmentAction::SelfInsert );
|
||||
// First try: minimize or replace perpandiculars first.
|
||||
if (Manipulator(_segment,fsm).minimize())
|
||||
fsm.addAction( _segment, SegmentAction::SelfInsert );
|
||||
else
|
||||
Manipulator(_segment,fsm).repackPerpandiculars( Manipulator::PerpandicularsFirst );
|
||||
fsm.doActions();
|
||||
queue.commit();
|
||||
break;
|
||||
case 2:
|
||||
// Second try: failed re-inserted first.
|
||||
Manipulator(_segment,fsm).repackPerpandiculars();
|
||||
fsm.addAction( _segment, SegmentAction::SelfInsert );
|
||||
Manipulator(_segment,fsm).repackPerpandiculars( 0 );
|
||||
//fsm.addAction( _segment, SegmentAction::SelfInsert );
|
||||
fsm.doActions();
|
||||
queue.commit();
|
||||
break;
|
||||
|
@ -635,6 +652,8 @@ namespace Katana {
|
|||
|
||||
void RoutingEvent::revalidate ()
|
||||
{
|
||||
if (_segment->isNonPref()) { _revalidateNonPref(); return; }
|
||||
|
||||
DebugSession::open( _segment->getNet(), 156, 160 );
|
||||
|
||||
cdebug_log(159,1) << "RoutingEvent::revalidate() - " << this << endl;
|
||||
|
@ -719,6 +738,66 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void RoutingEvent::_revalidateNonPref ()
|
||||
{
|
||||
DebugSession::open( _segment->getNet(), 156, 160 );
|
||||
|
||||
cdebug_log(159,1) << "RoutingEvent::_revalidateNonPref() - " << this << endl;
|
||||
|
||||
setAxisHintFromParent();
|
||||
cdebug_log(159,0) << "axisHint:" << DbU::getValueString(getAxisHint()) << endl;
|
||||
|
||||
_overConstrained = false;
|
||||
_segment->base()->getConstraints( _constraints );
|
||||
_segment->base()->getOptimal ( _optimal );
|
||||
|
||||
cdebug_log(159,0) << "Stage:" << RoutingEvent::getStage() << endl;
|
||||
cdebug_log(159,0) << "| Raw Track Constraint: " << _constraints
|
||||
<< " [" << _constraints.getVMin()
|
||||
<< "," << _constraints.getVMax() << "]" << endl;
|
||||
|
||||
_tracksNb = 0;
|
||||
|
||||
Interval perpandicular = _constraints;
|
||||
perpandicular.intersection( getPerpandicularFree() );
|
||||
cdebug_log(159,0) << "| Perpandicular Free: " << perpandicular << endl;
|
||||
|
||||
size_t depth = Session::getRoutingGauge()->getLayerDepth( _segment->getLayer() );
|
||||
|
||||
depth += (depth+1 <= Session::getConfiguration()->getAllowedDepth()) ? 1 : -1;
|
||||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( depth );
|
||||
|
||||
if (not perpandicular.isEmpty()) {
|
||||
Track* track = plane->getTrackByPosition( perpandicular.getVMin() );
|
||||
|
||||
if ( track and (track->getAxis() < perpandicular.getVMin()) ) track = track->getNextTrack();
|
||||
for ( ; track and (track->getAxis() <= perpandicular.getVMax())
|
||||
; track = track->getNextTrack(), _tracksNb++ );
|
||||
}
|
||||
if (not _tracksNb) {
|
||||
cdebug_log(159,0) << "| Reverting to pure constraints." << endl;
|
||||
Track* track = plane->getTrackByPosition( _constraints.getVMin() );
|
||||
|
||||
if ( track && (track->getAxis() < _constraints.getVMin()) ) track = track->getNextTrack();
|
||||
for ( ; track && (track->getAxis() <= _constraints.getVMax())
|
||||
; track = track->getNextTrack(), _tracksNb++ );
|
||||
}
|
||||
if (not _tracksNb) {
|
||||
cdebug_log(159,0) << "| Pure constraints are too tight." << endl;
|
||||
if (_segment->base())
|
||||
_overConstrained = _segment->base()->getAutoSource()->isTerminal()
|
||||
and _segment->base()->getAutoTarget()->isTerminal();
|
||||
}
|
||||
|
||||
_segment->computePriority();
|
||||
|
||||
cdebug_log(159,0) << _segment << " has " << (int)_tracksNb << " choices " << perpandicular << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
|
||||
DebugSession::close();
|
||||
}
|
||||
|
||||
|
||||
string RoutingEvent::_getTypeName () const
|
||||
{ return "RoutingEvent"; }
|
||||
|
||||
|
|
|
@ -95,9 +95,7 @@ namespace Katana {
|
|||
if (not plane->_layerGauge)
|
||||
throw Error( badLayerGauge, depth, getString(katana->getConfiguration()->getRoutingGauge()).c_str() );
|
||||
|
||||
DbU::Unit hExtension = 0;
|
||||
DbU::Unit vExtension = 0;
|
||||
uint32_t gaugeDepth = 0;
|
||||
uint32_t gaugeDepth = 0;
|
||||
if (Session::getLayerGauge(gaugeDepth)->getType() == Constant::PinOnly) ++gaugeDepth;
|
||||
|
||||
DbU::Unit extensionCap = ( std::max( Session::getWireWidth(depth), Session::getViaWidth(depth) )
|
||||
|
|
|
@ -366,19 +366,26 @@ namespace Katana {
|
|||
DebugSession::open( _segment->getNet(), 156, 160 );
|
||||
|
||||
if (_type & Lock) {
|
||||
cdebug_log(159,0) << "* Lock // " << _segment << endl;
|
||||
cdebug_log(159,1) << "* Lock // " << _segment << endl;
|
||||
} else if (_type & Perpandicular) {
|
||||
cdebug_log(159,0) << "* Riping Pp " << _segment << endl;
|
||||
cdebug_log(159,1) << "* Riping Pp " << _segment << endl;
|
||||
} else if (_type & OtherRipup) {
|
||||
cdebug_log(159,1) << "* Riping Other " << _segment << endl;
|
||||
} else {
|
||||
cdebug_log(159,0) << "* Riping // " << _segment << endl;
|
||||
cdebug_log(159,1) << "* Riping // " << _segment << endl;
|
||||
}
|
||||
|
||||
if (_segment->isFixed()) { DebugSession::close(); return true; }
|
||||
|
||||
DataNegociate* data = _segment->getDataNegociate();
|
||||
if (data == NULL) { DebugSession::close(); return true; }
|
||||
if (data == NULL) {
|
||||
cdebug_tabw(159,-1);
|
||||
DebugSession::close();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_type & ResetRipup) data->resetRipupCount();
|
||||
if (_type & ResetRipup ) data->resetRipupCount();
|
||||
if (_type & DecreaseRipup) data->decRipupCount ();
|
||||
|
||||
if (_type & ToState) {
|
||||
data->setState ( _toState );
|
||||
|
@ -433,6 +440,7 @@ namespace Katana {
|
|||
fork->setMode( mode );
|
||||
}
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
DebugSession::close();
|
||||
return true;
|
||||
}
|
||||
|
@ -547,29 +555,54 @@ namespace Katana {
|
|||
// _constraint.inflate ( 0, DbU::lambda(1.0) );
|
||||
|
||||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(segment1->getLayer());
|
||||
for ( Track* track1 : Tracks_Range::get(plane,_constraint) ) {
|
||||
Track* track2 = NULL;
|
||||
if (_event2) {
|
||||
track2 =
|
||||
(_sameAxis) ? track1 : plane->getTrackByPosition
|
||||
( segment2->getSymmetricAxis( symData->getSymmetrical( track1->getAxis() ) ) );
|
||||
|
||||
cdebug_log(155,0) << "refTrack:" << track1 << endl;
|
||||
cdebug_log(155,0) << "symTrack:" << track2 << endl;
|
||||
cdebug_log(155,0) << "by symData: " << DbU::getValueString( symData->getSymmetrical(track1->getAxis()) ) << endl;
|
||||
cdebug_log(155,0) << "plus segment2:" << DbU::getValueString( segment2->getSymmetricAxis(symData->getSymmetrical(track1->getAxis())) ) << endl;
|
||||
if (segment1->isNonPref()) {
|
||||
Track* baseTrack = plane->getTrackByPosition( segment1->base()->getSourcePosition(), Constant::Superior );
|
||||
|
||||
RoutingPlane* perpPlane = plane->getTop();
|
||||
if (not perpPlane) perpPlane = plane->getBottom();
|
||||
|
||||
for ( Track* ptrack : Tracks_Range::get(perpPlane,_constraint) ) {
|
||||
_costs.push_back( new TrackCost(segment1,NULL,baseTrack,NULL,ptrack->getAxis(),0) );
|
||||
|
||||
cdebug_log(155,0) << "AxisWeight:" << DbU::getValueString(_costs.back()->getRefCandidateAxis())
|
||||
<< " sum:" << DbU::getValueString(_costs.back()->getAxisWeight())
|
||||
<< endl;
|
||||
|
||||
if ( _fullBlocked and (not _costs.back()->isBlockage() and not _costs.back()->isFixed()) )
|
||||
_fullBlocked = false;
|
||||
|
||||
cdebug_log(155,0) << "| " << _costs.back() << ((_fullBlocked)?" FB ": " -- ") << ptrack << endl;
|
||||
}
|
||||
|
||||
_costs.push_back( new TrackCost(segment1,segment2,track1,track2) );
|
||||
} else {
|
||||
for ( Track* track1 : Tracks_Range::get(plane,_constraint) ) {
|
||||
Track* track2 = NULL;
|
||||
DbU::Unit symAxis = 0;
|
||||
if (_event2) {
|
||||
track2 =
|
||||
(_sameAxis) ? track1 : plane->getTrackByPosition
|
||||
( segment2->getSymmetricAxis( symData->getSymmetrical( track1->getAxis() ) ) );
|
||||
|
||||
if (track2) symAxis = track2->getAxis();
|
||||
|
||||
cdebug_log(155,0) << "refTrack:" << track1 << endl;
|
||||
cdebug_log(155,0) << "symTrack:" << track2 << endl;
|
||||
cdebug_log(155,0) << "by symData: " << DbU::getValueString( symData->getSymmetrical(track1->getAxis()) ) << endl;
|
||||
cdebug_log(155,0) << "plus segment2:" << DbU::getValueString( segment2->getSymmetricAxis(symData->getSymmetrical(track1->getAxis())) ) << endl;
|
||||
}
|
||||
|
||||
_costs.push_back( new TrackCost(segment1,segment2,track1,track2,track1->getAxis(),symAxis) );
|
||||
|
||||
cdebug_log(155,0) << "AxisWeight:" << DbU::getValueString(_costs.back()->getTrack()->getAxis())
|
||||
<< " sum:" << DbU::getValueString(_costs.back()->getAxisWeight())
|
||||
<< endl;
|
||||
cdebug_log(155,0) << "AxisWeight:" << DbU::getValueString(_costs.back()->getRefCandidateAxis())
|
||||
<< " sum:" << DbU::getValueString(_costs.back()->getAxisWeight())
|
||||
<< endl;
|
||||
|
||||
if ( _fullBlocked and (not _costs.back()->isBlockage() and not _costs.back()->isFixed()) )
|
||||
_fullBlocked = false;
|
||||
|
||||
if ( _fullBlocked and (not _costs.back()->isBlockage() and not _costs.back()->isFixed()) )
|
||||
_fullBlocked = false;
|
||||
|
||||
cdebug_log(155,0) << "| " << _costs.back() << ((_fullBlocked)?" FB ": " -- ") << track1 << endl;
|
||||
cdebug_log(155,0) << "| " << _costs.back() << ((_fullBlocked)?" FB ": " -- ") << track1 << endl;
|
||||
}
|
||||
}
|
||||
cdebug_tabw(159,-1);
|
||||
|
||||
|
@ -675,6 +708,7 @@ namespace Katana {
|
|||
}
|
||||
|
||||
_actions.clear ();
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
@ -731,7 +765,7 @@ namespace Katana {
|
|||
_event1->setEventLevel( 0 );
|
||||
|
||||
cdebug_log(9000,0) << "Deter| addInsertEvent() @" << getTrack1(i) << endl;
|
||||
Session::addInsertEvent( getSegment1(), getTrack1(i) );
|
||||
Session::addInsertEvent( getSegment1(), getTrack1(i), getCandidateAxis1(i) );
|
||||
|
||||
if (_event2) {
|
||||
_event2->resetInsertState();
|
||||
|
@ -740,7 +774,7 @@ namespace Katana {
|
|||
_event2->setProcessed( true );
|
||||
|
||||
cdebug_log(9000,0) << "Deter| addInsertEvent() @" << getTrack1(i) << endl;
|
||||
Session::addInsertEvent( getSegment2(), getTrack2(i) );
|
||||
Session::addInsertEvent( getSegment2(), getTrack2(i), getCandidateAxis2(i) );
|
||||
}
|
||||
|
||||
setState( SegmentFsm::SelfInserted );
|
||||
|
@ -751,11 +785,11 @@ namespace Katana {
|
|||
{
|
||||
cdebug_log(159,0) << "SegmentFsm::moveToTrack() :" << " track:" << i << endl;
|
||||
|
||||
Session::addMoveEvent( getSegment1(), getTrack1(i) );
|
||||
Session::addMoveEvent( getSegment1(), getTrack1(i), getCandidateAxis1(i) );
|
||||
|
||||
if (_event2) {
|
||||
cdebug_log(9000,0) << "Deter| addInsertEvent() @" << getTrack1(i) << endl;
|
||||
Session::addMoveEvent( getSegment2(), getTrack2(i) );
|
||||
Session::addMoveEvent( getSegment2(), getTrack2(i), getCandidateAxis2(i) );
|
||||
}
|
||||
|
||||
setState( SegmentFsm::SelfInserted );
|
||||
|
@ -848,13 +882,15 @@ namespace Katana {
|
|||
} else {
|
||||
cdebug_log(159,0) << "No disloggers found @" << DbU::getValueString(segment->getAxis()) << endl;
|
||||
|
||||
Interval freeSpan = Session::getKatanaEngine()->
|
||||
getTrackByPosition(segment->getLayer(),segment->getAxis())->
|
||||
getFreeInterval(segment->getSourceU(),segment->getNet());
|
||||
Track* track = Session::getKatanaEngine()->getTrackByPosition( segment->getLayer()
|
||||
, segment->getAxis () );
|
||||
if (track) {
|
||||
Interval freeSpan = track->getFreeInterval( segment->getSourceU(), segment->getNet() );
|
||||
|
||||
if (freeSpan.contains(segment->getCanonicalInterval())) {
|
||||
cdebug_log(159,0) << "Disloggers vanished, Segment can be re-inserted." << endl;
|
||||
success = true;
|
||||
if (freeSpan.contains(segment->getCanonicalInterval())) {
|
||||
cdebug_log(159,0) << "Disloggers vanished, Segment can be re-inserted." << endl;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,14 +1015,14 @@ namespace Katana {
|
|||
|
||||
if (Session::getConfiguration()->isVH() and (segment->getDepth() == 1)) {
|
||||
if (Manipulator(segment,*this).makeDogleg(overlap0,Flags::ShortDogleg)) {
|
||||
cerr << "Break using ShortDogleg." << endl;
|
||||
//cerr << "Break using ShortDogleg." << endl;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (other->isGlobal()) {
|
||||
cdebug_log(159,0) << "conflictSolveByPlaceds() - Conflict with global, other move up" << endl;
|
||||
if ((success = Manipulator(other,*this).moveUp())) break;
|
||||
if ((success = Manipulator(other,*this).moveUp(Manipulator::IgnoreContacts))) break;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "conflictSolveByPlaceds() - Relaxing self" << endl;
|
||||
|
@ -1065,7 +1101,7 @@ namespace Katana {
|
|||
success = Manipulator(segment,*this).moveUp
|
||||
(Manipulator::AllowLocalMoveUp|Manipulator::AllowTerminalMoveUp);
|
||||
}
|
||||
} else {
|
||||
} else if (not _costs.empty()) {
|
||||
Interval overlap = segment->getCanonicalInterval();
|
||||
size_t begin;
|
||||
size_t end;
|
||||
|
@ -1172,12 +1208,16 @@ namespace Katana {
|
|||
if (success) break;
|
||||
case DataNegociate::Minimize:
|
||||
if (data->getStateCount() >= 2) {
|
||||
nextState = DataNegociate::MaximumSlack;
|
||||
nextState = DataNegociate::Slacken;
|
||||
}
|
||||
success = manipulator.minimize();
|
||||
if (success) break;
|
||||
case DataNegociate::Dogleg:
|
||||
case DataNegociate::Slacken:
|
||||
if ((success = manipulator.slacken(Flags::HalfSlacken))) {
|
||||
nextState = DataNegociate::MaximumSlack;
|
||||
break;
|
||||
}
|
||||
case DataNegociate::ConflictSolveByHistory:
|
||||
case DataNegociate::ConflictSolveByPlaceds:
|
||||
case DataNegociate::MoveUp:
|
||||
|
@ -1231,11 +1271,11 @@ namespace Katana {
|
|||
if (success) break;
|
||||
}
|
||||
case DataNegociate::Dogleg:
|
||||
if (nextState == DataNegociate::Dogleg) {
|
||||
nextState = DataNegociate::Slacken;
|
||||
success = manipulator.makeDogleg();
|
||||
if (nextState == DataNegociate::Dogleg) {
|
||||
nextState = DataNegociate::Slacken;
|
||||
success = manipulator.makeDogleg();
|
||||
}
|
||||
if (success) break;
|
||||
}
|
||||
case DataNegociate::Slacken:
|
||||
if (nextState == DataNegociate::Slacken) {
|
||||
nextState = DataNegociate::ConflictSolveByPlaceds;
|
||||
|
@ -1324,7 +1364,7 @@ namespace Katana {
|
|||
cdebug_log(159,0) << "Global, SegmentFsm: Slacken "
|
||||
<< ((manipulator.getEvent())
|
||||
? manipulator.getEvent()->getConstraints() : "(no event yet)") << endl;
|
||||
if ( manipulator.getEvent()
|
||||
if ( manipulator.getEvent()
|
||||
and manipulator.getEvent()->getConstraints().isPonctual()
|
||||
and segment->canMoveUp(1.0,Flags::CheckLowUpDensity|Flags::AllowTerminal) ) {
|
||||
moveUpFlags |= Manipulator::AllowTerminalMoveUp;
|
||||
|
@ -1435,9 +1475,10 @@ namespace Katana {
|
|||
_data2->resetRipupCount();
|
||||
}
|
||||
|
||||
if (segment1->isStrap()) { success = _slackenStrap ( segment1, _data1, flags ); }
|
||||
else if (segment1->isLocal()) { success = _slackenLocal ( segment1, _data1, flags ); }
|
||||
else { success = _slackenGlobal( segment1, _data1, flags ); }
|
||||
if ( segment1->isStrap()
|
||||
or segment1->isUnbreakable()) { success = _slackenStrap ( segment1, _data1, flags ); }
|
||||
else if (segment1->isLocal()) { success = _slackenLocal ( segment1, _data1, flags ); }
|
||||
else { success = _slackenGlobal( segment1, _data1, flags ); }
|
||||
|
||||
if (success) {
|
||||
actionFlags |= SegmentAction::ResetRipup;
|
||||
|
@ -1445,6 +1486,9 @@ namespace Katana {
|
|||
actionFlags &= ~SegmentAction::EventLevel5;
|
||||
actionFlags |= SegmentAction::EventLevel3;
|
||||
}
|
||||
if (segment1->isNonPref()) {
|
||||
actionFlags &= ~SegmentAction::AllEventLevels;
|
||||
}
|
||||
addAction( segment1, actionFlags );
|
||||
} else {
|
||||
clearActions();
|
||||
|
|
|
@ -97,9 +97,10 @@ namespace Katana {
|
|||
|
||||
Session::Session ( KatanaEngine* katana )
|
||||
: Super(katana)
|
||||
, _insertEvents()
|
||||
, _removeEvents()
|
||||
, _sortEvents ()
|
||||
, _indirectInvalids()
|
||||
, _insertEvents ()
|
||||
, _removeEvents ()
|
||||
, _sortEvents ()
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -206,18 +207,25 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void Session::_doRemovalEvents ()
|
||||
void Session::_doRemovalEvents ( bool reschedule )
|
||||
{
|
||||
cdebug_log(159,1) << "Katana::Session::_doRemovalEvents()" << endl;
|
||||
|
||||
set<Track*> packTracks;
|
||||
|
||||
for ( size_t i=0 ; i<_removeEvents.size() ; ++i ) {
|
||||
cdebug_log(159,0) << "Event:" << _removeEvents[i]._segment << endl;
|
||||
|
||||
if (not _removeEvents[i]._segment->getTrack()) continue;
|
||||
_removeEvents[i]._segment->detach( packTracks );
|
||||
if (reschedule) _removeEvents[i]._segment->reschedule( 0 );
|
||||
}
|
||||
_removeEvents.clear();
|
||||
|
||||
for ( set<Track*>::iterator it=packTracks.begin() ; it != packTracks.end() ; ++it )
|
||||
(*it)->doRemoval();
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -236,18 +244,26 @@ namespace Katana {
|
|||
size_t Session::_revalidate ()
|
||||
{
|
||||
cdebug_log(159,1) << "Katana::Session::_revalidate()" << endl;
|
||||
uint32_t overlaps = 0;
|
||||
|
||||
//Track* checkTrack = NULL;
|
||||
//if (getKatanaEngine()->getRoutingPlaneByIndex( 1 ))
|
||||
// checkTrack = getKatanaEngine()->getRoutingPlaneByIndex( 1 )->getTrackByIndex( 87 );
|
||||
|
||||
_doLockEvents();
|
||||
_doRemovalEvents();
|
||||
//if (checkTrack) checkTrack->check( overlaps, "Session::_revalidate() - check track 82 @270." );
|
||||
|
||||
for ( const Event& event : _insertEvents ) {
|
||||
if (event._segment) {
|
||||
if (event._segment->isReduced()) event._segment->setAxis( event._track->getAxis() );
|
||||
else event._track->insert( event._segment );
|
||||
if (event._segment->getAxis() != event._axis) event._segment->setAxis( event._axis );
|
||||
if (not event._segment->isReduced()) event._track->insert( event._segment );
|
||||
}
|
||||
if (event._marker) event._track->insert( event._marker );
|
||||
}
|
||||
_insertEvents.clear();
|
||||
_doRemovalEvents( false );
|
||||
//if (checkTrack) checkTrack->check( overlaps, "Session::_revalidate() - check track 82 @270." );
|
||||
|
||||
// Check if to be destroyeds are not associateds with TrackSegments.
|
||||
const set<AutoSegment*>& destroyeds = getDestroyeds();
|
||||
|
@ -279,11 +295,11 @@ namespace Katana {
|
|||
}
|
||||
_doglegReset();
|
||||
|
||||
# if defined(CHECK_DATABASE)
|
||||
uint32_t overlaps = 0;
|
||||
# endif
|
||||
for ( Track* track : _sortEvents ) {
|
||||
track->doReorder();
|
||||
if (cdebug.enabled()) {
|
||||
track->check( overlaps, "Session::_revalidate() - track sorting." );
|
||||
}
|
||||
# if defined(CHECK_DATABASE)
|
||||
track->check( overlaps, "Session::_revalidate() - track sorting." );
|
||||
# endif
|
||||
|
@ -316,6 +332,22 @@ namespace Katana {
|
|||
}
|
||||
}
|
||||
|
||||
// for ( TrackElement* trackSegment : _indirectInvalids ) {
|
||||
// cdebug_log(159,0) << "Indirect reschedule:" << trackSegment << endl;
|
||||
// trackSegment->reschedule( 0 );
|
||||
// // addRemoveEvent( trackSegment );
|
||||
|
||||
// // if (trackSegment->getDataNegociate() and trackSegment->getDataNegociate()->hasRoutingEvent()) {
|
||||
// // RoutingEvent* event = trackSegment->getDataNegociate()->getRoutingEvent();
|
||||
// // if ( not event->isDisabled()
|
||||
// // and not event->isUnimplemented()
|
||||
// // and event->isProcessed()) {
|
||||
// // trackSegment->reschedule( 0 );
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
_indirectInvalids.clear();
|
||||
|
||||
_doRemovalEvents();
|
||||
for ( Track* track : _sortEvents ) track->doReorder();
|
||||
_sortEvents.clear();
|
||||
|
@ -353,10 +385,11 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void Session::_addInsertEvent ( TrackElement* segment, Track* track )
|
||||
void Session::_addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
|
||||
{
|
||||
cdebug_log(159,0) << "addInsertEvent() " << segment
|
||||
<< "\n @" << track << endl;
|
||||
<< "\n @" << DbU::getValueString(axis)
|
||||
<< " " << track << endl;
|
||||
|
||||
if ( segment->getTrack() != NULL ) {
|
||||
cerr << Bug("Session::addInsertEvent(): Segment already in Track."
|
||||
|
@ -368,7 +401,7 @@ namespace Katana {
|
|||
return;
|
||||
}
|
||||
|
||||
_insertEvents.push_back( Event(segment,track) );
|
||||
_insertEvents.push_back( Event(segment,track,axis) );
|
||||
_addSortEvent( track, true );
|
||||
}
|
||||
|
||||
|
@ -382,7 +415,7 @@ namespace Katana {
|
|||
}
|
||||
|
||||
cdebug_log(159,0) << "Ripup: @" << DbU::getValueString(segment->getAxis()) << " " << segment << endl;
|
||||
_removeEvents.push_back( Event(segment,segment->getTrack()) );
|
||||
_removeEvents.push_back( Event(segment,segment->getTrack(),segment->getAxis()) );
|
||||
_addSortEvent( segment->getTrack(), true );
|
||||
}
|
||||
|
||||
|
@ -396,11 +429,11 @@ namespace Katana {
|
|||
}
|
||||
|
||||
cdebug_log(159,0) << "Lock: @" << DbU::getValueString(segment->getAxis()) << " " << segment << endl;
|
||||
_lockEvents.push_back( Event(segment,NULL) );
|
||||
_lockEvents.push_back( Event(segment,NULL,0) );
|
||||
}
|
||||
|
||||
|
||||
void Session::_addMoveEvent ( TrackElement* segment, Track* track )
|
||||
void Session::_addMoveEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
|
||||
{
|
||||
if (not segment->getTrack()) {
|
||||
cerr << Bug( " Katana::Session::addMoveEvent() : %s is not yet in a track."
|
||||
|
@ -409,7 +442,7 @@ namespace Katana {
|
|||
_addRemoveEvent( segment );
|
||||
}
|
||||
|
||||
_addInsertEvent( segment, track );
|
||||
_addInsertEvent( segment, track, axis );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -93,11 +93,14 @@ namespace Katana {
|
|||
{
|
||||
cdebug_log(155,1) << "Track::_preDestroy() - " << (void*)this << " " << this << endl;
|
||||
|
||||
set<Track*> dummy;
|
||||
for ( size_t i=0 ; i<_segments.size() ; i++ )
|
||||
if (_segments[i]) {
|
||||
_segments[i]->detach();
|
||||
if (not _segments[i]->getTrackCount())
|
||||
_segments[i]->detach( dummy );
|
||||
if (not _segments[i]->getTrackCount()) {
|
||||
//cerr << "destroy " << _segments[i] << endl;
|
||||
_segments[i]->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i=0 ; i<_markers.size() ; i++ )
|
||||
|
@ -412,7 +415,8 @@ namespace Katana {
|
|||
|
||||
Interval Track::expandFreeInterval ( size_t& begin, size_t& end, uint32_t state, Net* net ) const
|
||||
{
|
||||
cdebug_log(155,1) << "Track::expandFreeInterval() begin:" << begin << " end:" << end << " " << net << endl;
|
||||
cdebug_log(155,1) << "Track::expandFreeInterval() begin:" << begin << " end:" << end
|
||||
<< " state:" << state << " " << net << endl;
|
||||
cdebug_log(155,0) << _segments[begin] << endl;
|
||||
|
||||
DbU::Unit minFree = _min;
|
||||
|
@ -433,6 +437,11 @@ namespace Katana {
|
|||
|
||||
if (_segments[end]->getNet() == net) {
|
||||
getNext( end, net );
|
||||
if (end != npos) {
|
||||
cdebug_log(155,0) << "| same net, end:" << end << " " << _segments[end] << endl;
|
||||
} else {
|
||||
cdebug_log(155,0) << "| same net, end:" << end << " (after last)" << endl;
|
||||
}
|
||||
|
||||
if (end == npos) {
|
||||
end = _segments.size() - 1;
|
||||
|
@ -440,7 +449,11 @@ namespace Katana {
|
|||
} else {
|
||||
setMaximalFlags( state, EndIsSegmentMin );
|
||||
}
|
||||
} else {
|
||||
state = EndIsTrackMax;
|
||||
cdebug_log(155,0) << "| already after last" << endl;
|
||||
}
|
||||
|
||||
cdebug_log(155,0) << "end:" << end << " state:" << state << endl;
|
||||
}
|
||||
|
||||
|
@ -474,14 +487,15 @@ namespace Katana {
|
|||
,getString(segment).c_str()) << endl;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Insert in [" << 0 << "] " << this << segment << endl;
|
||||
_segments.push_back( segment );
|
||||
_segmentsValid = false;
|
||||
|
||||
if (segment->isWide()) {
|
||||
cdebug_log(155,0) << "Segment is wide." << endl;
|
||||
if (segment->isWide() or segment->isNonPref()) {
|
||||
cdebug_log(155,0) << "Segment is wide or non-pref, trackSpan:" << segment->getTrackSpan() << endl;
|
||||
Track* wtrack = getNextTrack();
|
||||
for ( size_t i=1 ; wtrack and (i<segment->getTrackSpan()) ; ++i ) {
|
||||
cdebug_log(155,0) << "Insert in [" << i << "] " << wtrack << endl;
|
||||
cdebug_log(159,0) << "Insert in [" << i << "] " << wtrack << segment << endl;
|
||||
wtrack->_segments.push_back ( segment );
|
||||
wtrack->_segmentsValid = false;
|
||||
wtrack = wtrack->getNextTrack();
|
||||
|
@ -508,13 +522,21 @@ namespace Katana {
|
|||
if (message) cerr << " o Checking Track - " << message << endl;
|
||||
cdebug_log(155,0) << (void*)this << ":" << this << endl;
|
||||
|
||||
|
||||
for ( size_t i=0 ; i<_segments.size() ; i++ ) {
|
||||
Interval trackRange ( _segments[i]->getAxis() - (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2
|
||||
, _segments[i]->getAxis() + (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2 );
|
||||
bool inTrackRange = trackRange.contains( _axis );
|
||||
|
||||
if (_segments[i]) {
|
||||
bool inTrackRange = false;
|
||||
|
||||
if (_segments[i]->isNonPref()) {
|
||||
DbU::Unit min = 0;
|
||||
DbU::Unit max = 0;
|
||||
_segments[i]->base()->getCanonical( min, max );
|
||||
inTrackRange = Interval(min,max).contains( _axis );
|
||||
} else {
|
||||
Interval trackRange ( _segments[i]->getAxis() - (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2
|
||||
, _segments[i]->getAxis() + (_segments[i]->getTrackSpan()*_segments[i]->getPitch())/2 );
|
||||
inTrackRange = trackRange.contains( _axis );
|
||||
}
|
||||
|
||||
if (i) {
|
||||
if (_segments[i-1] == _segments[i]) {
|
||||
cerr << "[CHECK] incoherency at " << i << " "
|
||||
|
@ -598,7 +620,7 @@ namespace Katana {
|
|||
case EndIsTrackMax: return _max;
|
||||
case EndIsSegmentMin: return _segments[index ]->getSourceU ();
|
||||
case EndIsNextSegmentMin: if (index+1 >= getSize()) return _max;
|
||||
return _segments[index+1]->getSourceU ();
|
||||
return _segments[index+1]->getSourceU ();
|
||||
case EndIsSegmentMax: return _segments[index ]->getTargetU ();
|
||||
}
|
||||
|
||||
|
@ -655,7 +677,7 @@ namespace Katana {
|
|||
Interval mergedInterval;
|
||||
_segments[seed]->getCanonical( mergedInterval );
|
||||
|
||||
cdebug_log(155,0) << "| seed:" << _segments[seed] << endl;
|
||||
cdebug_log(155,0) << "| seed:" << mergedInterval << " " << _segments[seed] << endl;
|
||||
|
||||
size_t i = seed;
|
||||
while ( --i != npos ) {
|
||||
|
@ -663,7 +685,7 @@ namespace Katana {
|
|||
|
||||
_segments[i]->getCanonical ( segmentInterval );
|
||||
if (segmentInterval.getVMax() >= mergedInterval.getVMin()) {
|
||||
cdebug_log(155,0) << "| merge (prev):" << _segments[i] << endl;
|
||||
cdebug_log(155,0) << "| merge (prev):" << segmentInterval << " " << _segments[i] << endl;
|
||||
|
||||
mergedInterval.merge( segmentInterval );
|
||||
begin = i;
|
||||
|
@ -748,10 +770,12 @@ namespace Katana {
|
|||
|
||||
if ( (j<_segments.size())
|
||||
&& (_segments[i]->getTargetU() > _segments[j]->getSourceU()) ) {
|
||||
cerr << Error("Overlap in %s between:\n %s\n %s"
|
||||
cerr << Error("Overlap in %s between:\n %s\n %s\n TargetU:%s SourceU:%s"
|
||||
,getString(this).c_str()
|
||||
,getString(_segments[i]).c_str()
|
||||
,getString(_segments[j]).c_str()) << endl;
|
||||
,getString(_segments[j]).c_str()
|
||||
,DbU::getValueString(_segments[i]->getTargetU()).c_str()
|
||||
,DbU::getValueString(_segments[j]->getSourceU()).c_str() ) << endl;
|
||||
overlaps++;
|
||||
}
|
||||
}
|
||||
|
@ -763,7 +787,8 @@ namespace Katana {
|
|||
string Track::_getString () const
|
||||
{
|
||||
return "<" + _getTypeName() + " "
|
||||
+ getString(getLayer()) + " @"
|
||||
+ "[" + getString(_index) + "] "
|
||||
+ getString(getLayer()->getName()) + " @"
|
||||
+ DbU::getValueString(_axis) + " ["
|
||||
+ DbU::getValueString(_min) + ":"
|
||||
+ DbU::getValueString(_max) + "] ["
|
||||
|
|
|
@ -37,27 +37,45 @@ namespace Katana {
|
|||
, TrackElement* symSegment
|
||||
, Track* refTrack
|
||||
, Track* symTrack
|
||||
, DbU::Unit refCandidateAxis
|
||||
, DbU::Unit symCandidateAxis
|
||||
)
|
||||
: _flags ((symSegment) ? Symmetric : NoFlags)
|
||||
, _span (refSegment->getTrackSpan())
|
||||
, _tracks ( _span * ((symSegment) ? 2 : 1)
|
||||
, std::tuple<Track*,size_t,size_t>(NULL,Track::npos,Track::npos) )
|
||||
, _segment1 (refSegment)
|
||||
, _segment2 (symSegment)
|
||||
, _interval1 (refSegment->getCanonicalInterval())
|
||||
, _interval2 ((symSegment) ? symSegment->getCanonicalInterval() : Interval())
|
||||
, _terminals (0)
|
||||
, _delta (-_interval1.getSize() -_interval2.getSize())
|
||||
, _deltaShared (0)
|
||||
, _deltaPerpand (0)
|
||||
, _axisWeight (0)
|
||||
, _distanceToFixed(2*Session::getSliceHeight())
|
||||
, _longuestOverlap(0)
|
||||
, _dataState (0)
|
||||
, _ripupCount (0)
|
||||
, _selectFlags (NoFlags)
|
||||
, _selectIndex (0)
|
||||
: _flags ((symSegment) ? Symmetric : NoFlags)
|
||||
, _span (refSegment->getTrackSpan())
|
||||
, _refCandidateAxis(refCandidateAxis)
|
||||
, _symCandidateAxis(refCandidateAxis)
|
||||
, _tracks ( _span * ((symSegment) ? 2 : 1)
|
||||
, std::tuple<Track*,size_t,size_t>(NULL,Track::npos,Track::npos) )
|
||||
, _segment1 (refSegment)
|
||||
, _segment2 (symSegment)
|
||||
, _interval1 (refSegment->getCanonicalInterval())
|
||||
, _interval2 ((symSegment) ? symSegment->getCanonicalInterval() : Interval())
|
||||
, _terminals (0)
|
||||
, _delta (-_interval1.getSize() -_interval2.getSize())
|
||||
, _deltaShared (0)
|
||||
, _deltaPerpand (0)
|
||||
, _axisWeight (0)
|
||||
, _distanceToFixed (2*Session::getSliceHeight())
|
||||
, _longuestOverlap (0)
|
||||
, _dataState (0)
|
||||
, _ripupCount (0)
|
||||
, _selectFlags (NoFlags)
|
||||
, _selectIndex (0)
|
||||
{
|
||||
if (refSegment->isNonPref()) {
|
||||
DbU::Unit axisShift = getRefCandidateAxis() - refSegment->getAxis();
|
||||
_interval1.translate( axisShift );
|
||||
|
||||
if (symSegment) {
|
||||
throw Error( "TrackCost::TrackCost(): Symmetric management is not implemented for Non-preferred routing segments.\n"
|
||||
" %s", getString(refSegment).c_str() );
|
||||
}
|
||||
}
|
||||
if (not _span) {
|
||||
throw Error( "TrackCost::TrackCost(): Zero track span is not allowed.\n"
|
||||
" %s", getString(refSegment).c_str() );
|
||||
}
|
||||
|
||||
cdebug_log(159,1) << "TrackCost::TrackCost() - " << refSegment << endl;
|
||||
cdebug_log(159,0) << " interval1: " << _interval1 << endl;
|
||||
|
||||
|
@ -87,7 +105,8 @@ namespace Katana {
|
|||
|
||||
bool TrackCost::Compare::operator() ( const TrackCost* lhs, const TrackCost* rhs )
|
||||
{
|
||||
if ( lhs->isInfinite() xor rhs->isInfinite() ) return rhs->isInfinite();
|
||||
if ( lhs->isInfinite () xor rhs->isInfinite () ) return rhs->isInfinite();
|
||||
if ( lhs->isAtRipupLimit() xor rhs->isAtRipupLimit() ) return rhs->isAtRipupLimit();
|
||||
|
||||
if ( (_flags & TrackCost::DiscardGlobals)
|
||||
and (lhs->isOverlapGlobal() xor rhs->isOverlapGlobal()) )
|
||||
|
@ -160,8 +179,8 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
Net* TrackCost::getNet1 () const { return (_segment1) ? _segment1->getNet() : NULL; }
|
||||
Net* TrackCost::getNet2 () const { return (_segment2) ? _segment2->getNet() : NULL; }
|
||||
Net* TrackCost::getNet1 () const { return (_segment1) ? _segment1->getNet() : NULL; }
|
||||
Net* TrackCost::getNet2 () const { return (_segment2) ? _segment2->getNet() : NULL; }
|
||||
|
||||
|
||||
size_t TrackCost::getBegin ( size_t i, uint32_t flags ) const
|
||||
|
@ -232,7 +251,8 @@ namespace Katana {
|
|||
{
|
||||
string s = "<" + _getTypeName();
|
||||
|
||||
s += " " + getString(getTrack(0));
|
||||
s += " @" + DbU::getValueString(getRefCandidateAxis());
|
||||
s += " " + getString(getTrack(0)->getLayer()->getName());
|
||||
s += " " + getString(_dataState);
|
||||
s += "+" + getString(_ripupCount);
|
||||
s += ":" + getString((_dataState<<2)+_ripupCount);
|
||||
|
@ -243,6 +263,7 @@ namespace Katana {
|
|||
s += string ( (isOverlap() )?"o":"-" );
|
||||
s += string ( (isOverlapGlobal() )?"g":"-" );
|
||||
s += string ( (isGlobalEnclosed())?"e":"-" );
|
||||
s += string ( (isAtRipupLimit ())?"R":"-" );
|
||||
s += string ( (isAnalog ())?"a":"-" );
|
||||
s += string ( (isShortNet ())?"N":"-" );
|
||||
s += " " + getString(_terminals);
|
||||
|
|
|
@ -141,6 +141,7 @@ namespace Katana {
|
|||
bool TrackElement::isDrag () const { return false; }
|
||||
bool TrackElement::isStrongTerminal ( Flags ) const { return false; }
|
||||
bool TrackElement::isStrap () const { return false; }
|
||||
bool TrackElement::isUnbreakable () const { return false; }
|
||||
bool TrackElement::isSlackened () const { return false; }
|
||||
bool TrackElement::isDogleg () const { return false; }
|
||||
bool TrackElement::isShortDogleg () const { return false; }
|
||||
|
@ -149,6 +150,7 @@ namespace Katana {
|
|||
bool TrackElement::isUserDefined () const { return false; }
|
||||
bool TrackElement::isAnalog () const { return false; }
|
||||
bool TrackElement::isWide () const { return false; }
|
||||
bool TrackElement::isNonPref () const { return false; }
|
||||
bool TrackElement::isShortNet () const { return false; }
|
||||
// Predicates.
|
||||
bool TrackElement::hasSymmetric () const { return false; }
|
||||
|
@ -175,7 +177,6 @@ namespace Katana {
|
|||
DataNegociate* TrackElement::getDataNegociate ( Flags ) const { return NULL; }
|
||||
TrackElements TrackElement::getPerpandiculars () { return new TrackElements_Perpandiculars(NULL); }
|
||||
void TrackElement::invalidate () { }
|
||||
TrackElement* TrackElement::getCanonical ( Interval& i ) { i=Interval(getSourceU(),getTargetU()); return this; }
|
||||
TrackElement* TrackElement::getSourceDogleg () { return NULL; }
|
||||
TrackElement* TrackElement::getTargetDogleg () { return NULL; }
|
||||
TrackElement* TrackElement::getSymmetric () { return NULL; }
|
||||
|
@ -187,10 +188,11 @@ namespace Katana {
|
|||
void TrackElement::setDoglegLevel ( uint32_t ) { }
|
||||
void TrackElement::swapTrack ( TrackElement* ) { }
|
||||
void TrackElement::reschedule ( uint32_t ) { }
|
||||
void TrackElement::detach () { }
|
||||
//void TrackElement::detach () { }
|
||||
void TrackElement::detach ( set<Track*>& ) { }
|
||||
void TrackElement::revalidate () { }
|
||||
void TrackElement::updatePPitch () { }
|
||||
void TrackElement::updateTrackSpan () { }
|
||||
void TrackElement::setAxis ( DbU::Unit, uint32_t flags ) { }
|
||||
TrackElement* TrackElement::makeDogleg () { return NULL; }
|
||||
Flags TrackElement::makeDogleg ( Interval, TrackElement*&, TrackElement*&, Flags ) { return Flags::NoFlags; }
|
||||
|
|
|
@ -74,16 +74,24 @@ namespace Katana {
|
|||
const Layer* layer1 = track->getLayer()->getBlockageLayer();
|
||||
RegularLayer* layer2 = dynamic_cast<RegularLayer*>(technology->getLayer(layer1->getMask()));
|
||||
if ( layer2 ) {
|
||||
Interval uside = track->getKatanaEngine()->getUSide( track->getDirection() );
|
||||
Interval segside;
|
||||
//cerr << track->getLayer() << " minSpace:" << DbU::getValueString(track->getLayer()->getMinimalSpacing()) << endl;
|
||||
|
||||
Interval segside;
|
||||
Interval uside = track->getKatanaEngine()->getUSide( track->getDirection() );
|
||||
DbU::Unit cap = track->getLayer()->getMinimalSpacing()/2 /*+ track->getLayer()->getExtentionCap()*/;
|
||||
if (track->getDirection() == Flags::Horizontal) {
|
||||
segside = Interval( boundingBox.getXMin(), boundingBox.getXMax() );
|
||||
_sourceU = max( boundingBox.getXMin(), uside.getVMin());
|
||||
_targetU = min( boundingBox.getXMax(), uside.getVMax());
|
||||
_sourceU = max( boundingBox.getXMin() - cap, uside.getVMin());
|
||||
_targetU = min( boundingBox.getXMax() + cap, uside.getVMax());
|
||||
} else {
|
||||
segside = Interval( boundingBox.getYMin(), boundingBox.getYMax() );
|
||||
_sourceU = max( boundingBox.getYMin(), uside.getVMin());
|
||||
_targetU = min( boundingBox.getYMax(), uside.getVMax());
|
||||
_sourceU = max( boundingBox.getYMin() - cap, uside.getVMin());
|
||||
_targetU = min( boundingBox.getYMax() + cap, uside.getVMax());
|
||||
}
|
||||
|
||||
Flags gcellFlags = Flags::NoFlags;
|
||||
if (segment->getNet()->isSupply() and (depth > 0)) {
|
||||
gcellFlags |= Flags::GoStraight;
|
||||
}
|
||||
|
||||
GCellsUnder gcells = track->getKatanaEngine()->getGCellsUnder( segment );
|
||||
|
@ -91,6 +99,7 @@ namespace Katana {
|
|||
GCell* gcell = gcells->gcellAt(i);
|
||||
gcell->addBlockage
|
||||
( depth, gcell->getSide( track->getDirection() ).getIntersection( segside ).getSize() );
|
||||
gcell->flags() |= gcellFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +133,7 @@ namespace Katana {
|
|||
cdebug_log(159,0) << "Adding: " << segment << " on " << track << endl;
|
||||
cdebug_log(159,0) << "TrackFixedSegment::create(): " << trackFixedSegment << endl;
|
||||
|
||||
Session::addInsertEvent( trackFixedSegment, track );
|
||||
Session::addInsertEvent( trackFixedSegment, track, track->getAxis() );
|
||||
}
|
||||
return trackFixedSegment;
|
||||
}
|
||||
|
@ -132,7 +141,7 @@ namespace Katana {
|
|||
|
||||
AutoSegment* TrackFixedSegment::base () const { return NULL; }
|
||||
Segment* TrackFixedSegment::getSegment () const { return _segment; }
|
||||
DbU::Unit TrackFixedSegment::getAxis () const { return getTrack()->getAxis(); }
|
||||
DbU::Unit TrackFixedSegment::getAxis () const { return getTrack() ? getTrack()->getAxis() : 0; }
|
||||
bool TrackFixedSegment::isHorizontal () const { return getTrack()->isHorizontal(); }
|
||||
bool TrackFixedSegment::isVertical () const { return getTrack()->isVertical(); }
|
||||
bool TrackFixedSegment::isFixed () const { return true; }
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <sstream>
|
||||
#include <limits>
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/Net.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
#include "katana/DataNegociate.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/TrackSegmentRegular.h"
|
||||
#include "katana/TrackSegmentNonPref.h"
|
||||
#include "katana/TrackSegmentWide.h"
|
||||
#include "katana/Track.h"
|
||||
#include "katana/Session.h"
|
||||
|
@ -42,6 +44,7 @@ namespace Katana {
|
|||
using Hurricane::tab;
|
||||
using Hurricane::ForEachIterator;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::BasicLayer;
|
||||
using Hurricane::Net;
|
||||
|
@ -129,22 +132,36 @@ namespace Katana {
|
|||
|
||||
TrackElement* TrackSegment::create ( AutoSegment* segment, Track* track, bool& created )
|
||||
{
|
||||
DebugSession::open( segment->getNet(), 159, 160 );
|
||||
|
||||
created = false;
|
||||
|
||||
bool useNonPref = (segment->getDirection() xor Session::getDirection(segment->getLayer()));
|
||||
|
||||
DbU::Unit defaultWireWidth = Session::getWireWidth( segment->base()->getLayer() );
|
||||
TrackElement* trackElement = Session::lookup( segment->base() );
|
||||
if (not trackElement) {
|
||||
if (segment->base()->getWidth() <= defaultWireWidth)
|
||||
trackElement = new TrackSegmentRegular( segment, track );
|
||||
else
|
||||
trackElement = new TrackSegmentWide ( segment, track );
|
||||
if (useNonPref) {
|
||||
trackElement = new TrackSegmentNonPref( segment );
|
||||
if (track)
|
||||
cerr << Error( "TrackSegment::create(): Must not set track when creating a non-preferred element.\n"
|
||||
" (on %s)", getString(segment).c_str() ) << endl;
|
||||
} else {
|
||||
if (segment->base()->getWidth() <= defaultWireWidth)
|
||||
trackElement = new TrackSegmentRegular( segment, track );
|
||||
else
|
||||
trackElement = new TrackSegmentWide ( segment, track );
|
||||
}
|
||||
|
||||
trackElement->_postCreate();
|
||||
trackElement->invalidate();
|
||||
created = true;
|
||||
cdebug_log(159,0) << "TrackSegment::create(): " << trackElement << endl;
|
||||
cdebug_log(159,0) << "TrackSegment::create(): " << "nonPref:" <<useNonPref
|
||||
<< " " << trackElement << endl;
|
||||
}
|
||||
|
||||
DebugSession::close();
|
||||
|
||||
return trackElement;
|
||||
}
|
||||
|
||||
|
@ -159,6 +176,7 @@ namespace Katana {
|
|||
bool TrackSegment::isVertical () const { return _base->isVertical(); }
|
||||
bool TrackSegment::isLocal () const { return not _base->isWeakGlobal() and not _base->isGlobal(); }
|
||||
bool TrackSegment::isGlobal () const { return _base->isWeakGlobal() or _base->isGlobal(); }
|
||||
bool TrackSegment::isUnbreakable () const { return _base->isUnbreakable(); }
|
||||
bool TrackSegment::isBipoint () const { return _base->isBipoint(); }
|
||||
bool TrackSegment::isTerminal () const { return _base->isTerminal(); }
|
||||
bool TrackSegment::isDrag () const { return _base->isDrag(); }
|
||||
|
@ -192,7 +210,6 @@ namespace Katana {
|
|||
uint32_t TrackSegment::getDoglegLevel () const { return _dogLegLevel; }
|
||||
Interval TrackSegment::getSourceConstraints () const { return _base->getSourceConstraints(); }
|
||||
Interval TrackSegment::getTargetConstraints () const { return _base->getTargetConstraints(); }
|
||||
TrackElement* TrackSegment::getCanonical ( Interval& i ) { return Session::lookup( _base->getCanonical(i)->base() ); }
|
||||
TrackElement* TrackSegment::getSymmetric () { return _symmetric; }
|
||||
TrackElements TrackSegment::getPerpandiculars () { return new TrackElements_Perpandiculars(this); }
|
||||
// Mutators.
|
||||
|
@ -389,13 +406,20 @@ namespace Katana {
|
|||
{
|
||||
if (track) {
|
||||
DbU::Unit axis = track->getAxis();
|
||||
if (getTrackSpan() > 1) {
|
||||
if (isWide()) {
|
||||
DbU::Unit pitch = track->getRoutingPlane()->getLayerGauge()->getPitch();
|
||||
axis += (pitch * (getTrackSpan() - 1)) / 2;
|
||||
|
||||
|
||||
cdebug_log(155,0) << "TrackSegment::setTrack(): pitch:" << DbU::getValueString(pitch)
|
||||
<< " trackSpan:" << getTrackSpan() << endl;
|
||||
}
|
||||
if (isNonPref()) {
|
||||
axis = getAxis();
|
||||
|
||||
cdebug_log(155,0) << "TrackSegment::setTrack(): Non-preferred, keep @" << DbU::getValueString(axis)
|
||||
<< " trackSpan:" << getTrackSpan() << endl;
|
||||
}
|
||||
|
||||
addTrackCount( getTrackSpan() );
|
||||
setAxis( axis, AutoSegment::SegAxisSet );
|
||||
}
|
||||
|
@ -407,28 +431,36 @@ namespace Katana {
|
|||
{ _symmetric = dynamic_cast<TrackSegment*>( segment ); }
|
||||
|
||||
|
||||
void TrackSegment::detach ()
|
||||
{
|
||||
cdebug_log(159,0) << "TrackSegment::detach() - <id:" << getId() << ">" << endl;
|
||||
// void TrackSegment::detach ()
|
||||
// {
|
||||
// cdebug_log(159,0) << "TrackSegment::detach() - <id:" << getId() << ">" << endl;
|
||||
|
||||
setTrack( NULL );
|
||||
setFlags( TElemLocked );
|
||||
addTrackCount( -1 );
|
||||
}
|
||||
// setTrack( NULL );
|
||||
// setFlags( TElemLocked );
|
||||
// addTrackCount( -1 );
|
||||
// }
|
||||
|
||||
|
||||
void TrackSegment::detach ( set<Track*>& removeds )
|
||||
{
|
||||
cdebug_log(159,0) << "TrackSegment::detach(set<Track*>&) - <id:" << getId() << ">" << endl;
|
||||
cdebug_log(159,1) << "TrackSegment::detach(set<Track*>&) - <id:" << getId() << "> trackSpan:"
|
||||
<< getTrackSpan() << endl;
|
||||
|
||||
Track* wtrack = getTrack();
|
||||
for ( size_t i=0 ; wtrack and (i<getTrackSpan()) ; ++i ) {
|
||||
|
||||
removeds.insert( wtrack );
|
||||
cdebug_log(159,0) << "| " << wtrack << endl;
|
||||
|
||||
wtrack = wtrack->getNextTrack();
|
||||
}
|
||||
//addTrackCount( -getTrackSpan() );
|
||||
addTrackCount( -1 );
|
||||
|
||||
detach();
|
||||
//detach();
|
||||
setTrack( NULL );
|
||||
setFlags( TElemLocked );
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -437,9 +469,25 @@ namespace Katana {
|
|||
unsetFlags( TElemCreated );
|
||||
cdebug_log(159,0) << "revalidate() - " << this << endl;
|
||||
|
||||
_base->getCanonical( _sourceU, _targetU );
|
||||
if (isNonPref()) {
|
||||
Interval perpandicularSpan ( getAxis() );
|
||||
perpandicularSpan.inflate( base()->getExtensionCap( Anabatic::Flags::Source ) );
|
||||
|
||||
if (_track) Session::addSortEvent( _track, true );
|
||||
_sourceU = perpandicularSpan.getVMin();
|
||||
_targetU = perpandicularSpan.getVMax();
|
||||
}
|
||||
else
|
||||
_base->getCanonical( _sourceU, _targetU );
|
||||
|
||||
if (isNonPref()) updateTrackSpan();
|
||||
|
||||
if (_track) {
|
||||
Track* wtrack = getTrack();
|
||||
for ( size_t i=0 ; wtrack and (i<getTrackSpan()) ; ++i ) {
|
||||
Session::addSortEvent( wtrack, true );
|
||||
wtrack = wtrack->getNextTrack();
|
||||
}
|
||||
}
|
||||
unsetFlags( TElemInvalidated );
|
||||
}
|
||||
|
||||
|
@ -782,6 +830,23 @@ namespace Katana {
|
|||
cdebug_log(159,0) << "Source: " << *gcells.begin () << endl;
|
||||
cdebug_log(159,0) << "Target: " << *gcells.rbegin() << endl;
|
||||
|
||||
AutoContact* acSource = base()->getAutoSource();
|
||||
AutoContact* acTarget = base()->getAutoTarget();
|
||||
if (gcells[0] == doglegGCell) {
|
||||
if (acSource->isHDogleg() or acSource->isVDogleg()) {
|
||||
cdebug_log(159,0) << "false: Source perpandicular already has a dogleg." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (gcells[gcells.size()-1] == doglegGCell) {
|
||||
if (acTarget->isHDogleg() or acTarget->isVDogleg()) {
|
||||
cdebug_log(159,0) << "false: Target perpandicular already has a dogleg." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isGCellInside = false;
|
||||
for ( size_t igcell=0 ; igcell<gcells.size() ; ++igcell ) {
|
||||
if (doglegGCell != gcells[igcell]) continue;
|
||||
|
@ -996,7 +1061,17 @@ namespace Katana {
|
|||
DbU::Unit min;
|
||||
DbU::Unit max;
|
||||
base()->checkPositions();
|
||||
base()->getCanonical( min, max );
|
||||
|
||||
if (isNonPref()) {
|
||||
Interval perpandicularSpan ( getAxis() );
|
||||
perpandicularSpan.inflate( base()->getExtensionCap( Anabatic::Flags::Source ) );
|
||||
|
||||
min = perpandicularSpan.getVMin();
|
||||
max = perpandicularSpan.getVMax();
|
||||
}
|
||||
else
|
||||
_base->getCanonical( min, max );
|
||||
|
||||
if (getSourceU() != min) {
|
||||
cerr << "[CHECK] " << this << " has bad source position "
|
||||
<< "cache:" << DbU::getValueString(getSourceU()) << " vs. "
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Universite 2019-2019, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | K i t e - D e t a i l e d R o u t e r |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./TrackSegmentNonPref.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Name.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "anabatic/AutoContact.h"
|
||||
#include "anabatic/GCell.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "katana/DataNegociate.h"
|
||||
#include "katana/TrackSegmentNonPref.h"
|
||||
#include "katana/Track.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/Session.h"
|
||||
#include "katana/RoutingEvent.h"
|
||||
#include "katana/NegociateWindow.h"
|
||||
#include "katana/KatanaEngine.h"
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
||||
using namespace std;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::BasicLayer;
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Name;
|
||||
using Hurricane::RoutingPad;
|
||||
using Anabatic::AutoSegment;
|
||||
using Anabatic::perpandicularTo;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "TrackSegmentNonPref".
|
||||
|
||||
|
||||
TrackSegmentNonPref::TrackSegmentNonPref ( AutoSegment* segment )
|
||||
: Super(segment,NULL)
|
||||
, _trackSpan (0)
|
||||
, _trackCount(0)
|
||||
{
|
||||
cdebug_log(159,1) << "CTOR TrackSegmentNonPref " << (void*)this << ":" << this << endl;
|
||||
cdebug_log(159,0) << " over " << (void*)segment << ":" << segment << endl;
|
||||
|
||||
updateTrackSpan();
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
||||
void TrackSegmentNonPref::_postCreate ()
|
||||
{
|
||||
Super::_postCreate();
|
||||
}
|
||||
|
||||
|
||||
TrackSegmentNonPref::~TrackSegmentNonPref ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void TrackSegmentNonPref::_preDestroy ()
|
||||
{
|
||||
Super::_preDestroy();
|
||||
}
|
||||
|
||||
|
||||
bool TrackSegmentNonPref::isNonPref () const { return true; }
|
||||
size_t TrackSegmentNonPref::getTrackSpan () const { return _trackSpan; }
|
||||
uint32_t TrackSegmentNonPref::getTrackCount () const { return _trackCount; }
|
||||
|
||||
|
||||
void TrackSegmentNonPref::updateTrackSpan ()
|
||||
{
|
||||
DebugSession::open( getNet(), 150, 160 );
|
||||
cdebug_log(159,1) << "TrackSegmentNonPref::updateTrackspan() " << (void*)this << ":" << this << endl;
|
||||
|
||||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_base->getLayer());
|
||||
Interval newAxisSpan ( _base->getSourcePosition(), _base->getTargetPosition() );
|
||||
Track* ntrack = plane->getTrackByPosition( newAxisSpan.getVMin(), Constant::Superior );
|
||||
|
||||
cdebug_log(159,0) << "new Axis span: " << newAxisSpan << endl;
|
||||
|
||||
if (ntrack) {
|
||||
cdebug_log(159,0) << "+ " << ntrack << endl;
|
||||
_trackSpan = 0;
|
||||
for ( ; ntrack and newAxisSpan.contains(ntrack->getAxis())
|
||||
; ntrack = ntrack->getNextTrack(), _trackSpan++ ) {
|
||||
cdebug_log(159,0) << "| " << ntrack << endl;
|
||||
}
|
||||
}
|
||||
if (not _trackSpan) _trackSpan = 1;
|
||||
cdebug_log(159,0) << "_trackSpan: " << _trackSpan << endl;
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
DebugSession::close();
|
||||
}
|
||||
|
||||
|
||||
void TrackSegmentNonPref::addTrackCount ( int32_t count )
|
||||
{
|
||||
if (count > 0) _trackCount += count;
|
||||
else {
|
||||
if (-count > (int32_t)_trackCount) _trackCount = 0;
|
||||
_trackCount -= -count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TrackSegmentNonPref::addOverlapCost ( TrackCost& cost ) const
|
||||
{
|
||||
uint32_t depth = Session::getRoutingGauge()->getLayerDepth(getLayer());
|
||||
bool inLocalDepth = (depth < 3);
|
||||
Track* track = cost.getTrack();
|
||||
|
||||
if (not track) return;
|
||||
DbU::Unit axisCandidate = cost.getRefCandidateAxis();
|
||||
|
||||
cost.setFlags( (isLocal() and (depth >= 3)) ? TrackCost::LocalAndTopDepth : 0 );
|
||||
cost.setFlags( (isAnalog()) ? TrackCost::Analog : 0 );
|
||||
cost.setDistanceToFixed();
|
||||
cost.incAxisWeight ( getDataNegociate()->getRoutingEvent()->getAxisWeight( axisCandidate ) );
|
||||
cost.incDeltaPerpand( getDataNegociate()->getWiringDelta( axisCandidate ) );
|
||||
|
||||
cdebug_log(155,0) << "incAxisWeight:" << DbU::getValueString(axisCandidate)
|
||||
<< " of " << DbU::getValueString(getDataNegociate()->getRoutingEvent()->getAxisWeight( axisCandidate ))
|
||||
<< " (sum:" << DbU::getValueString(cost.getAxisWeight()) << ")"
|
||||
<< endl;
|
||||
|
||||
for ( size_t span=0 ; (span < _trackSpan) and (track != NULL) ; ++span ) {
|
||||
track->addOverlapCost( cost );
|
||||
// Todo: have to choose here wether we go *next* or *previous* according
|
||||
// to the symmetry kind.
|
||||
track = track->getNextTrack();
|
||||
cost.selectNextTrack();
|
||||
}
|
||||
|
||||
if (isGlobal()) cost.setForGlobal();
|
||||
|
||||
if ( inLocalDepth and (cost.getDataState() == DataNegociate::MaximumSlack) )
|
||||
cost.setInfinite();
|
||||
|
||||
cost.select( 0, TrackCost::NoFlags );
|
||||
}
|
||||
|
||||
|
||||
void TrackSegmentNonPref::invalidate ()
|
||||
{
|
||||
if (isInvalidated()) return;
|
||||
|
||||
Super::invalidate();
|
||||
|
||||
if (getTrack()) reschedule( 0 );
|
||||
}
|
||||
|
||||
|
||||
} // Katana namespace.
|
|
@ -90,13 +90,13 @@ namespace Katana {
|
|||
|
||||
cost.setFlags( (isLocal() and (depth >= 3)) ? TrackCost::LocalAndTopDepth : 0 );
|
||||
cost.setFlags( (isAnalog()) ? TrackCost::Analog : 0 );
|
||||
if (isGlobal()) cost.setForGlobal();
|
||||
|
||||
track->addOverlapCost( cost );
|
||||
|
||||
cost.setDistanceToFixed();
|
||||
cost.incAxisWeight ( getDataNegociate()->getRoutingEvent()->getAxisWeight(track->getAxis()) );
|
||||
cost.incDeltaPerpand ( getDataNegociate()->getWiringDelta(track->getAxis()) );
|
||||
if (isGlobal()) cost.setForGlobal();
|
||||
|
||||
if ( inLocalDepth and (cost.getDataState() == DataNegociate::MaximumSlack) )
|
||||
cost.setInfinite();
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace Katana {
|
|||
|
||||
_track = routingPlane->getTrackByPosition ( _constraints.getVMin() );
|
||||
cdebug_log(155,0) << "* Nearest track: " << _track << endl;;
|
||||
cdebug_log(155,0) << "* axis:" << _track->getAxis() << " vmin:" << _constraints.getVMin() << endl;
|
||||
cdebug_log(155,0) << "* axis:" << ((_track) ? DbU::getValueString(_track->getAxis()) : string("None"))
|
||||
<< " vmin:" << _constraints.getVMin() << endl;
|
||||
|
||||
if ( _track and (_track->getAxis() < _constraints.getVMin()) ) _track = _track->getNextTrack();
|
||||
if ( _track and (_track->getAxis() > _constraints.getVMax()) ) _track = NULL;
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Katana {
|
|||
bool isCaged ( DbU::Unit ) const;
|
||||
bool ripup ( uint32_t type, DbU::Unit axisHint=0 );
|
||||
bool ripupPerpandiculars ( uint32_t flags=0 );
|
||||
void repackPerpandiculars ();
|
||||
void repackPerpandiculars ( uint32_t flags );
|
||||
void reprocessPerpandiculars ();
|
||||
bool ripple ();
|
||||
bool minimize ();
|
||||
|
|
|
@ -66,7 +66,8 @@ namespace Katana {
|
|||
Key ( const RoutingEvent* );
|
||||
void update ( const RoutingEvent* );
|
||||
private:
|
||||
unsigned int _tracksNb:16;
|
||||
unsigned int _tracksNb :16;
|
||||
unsigned int _rpDistance: 4;
|
||||
float _priority;
|
||||
uint32_t _eventLevel;
|
||||
uint32_t _segFlags;
|
||||
|
@ -135,6 +136,7 @@ namespace Katana {
|
|||
inline uint32_t getInsertState () const;
|
||||
inline uint32_t getEventLevel () const;
|
||||
void revalidate ();
|
||||
void _revalidateNonPref ();
|
||||
inline void updateKey ();
|
||||
void process ( RoutingEventQueue&
|
||||
, RoutingEventHistory&
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace Katana {
|
|||
|
||||
protected:
|
||||
// Attributes.
|
||||
KatanaEngine* _katana;
|
||||
KatanaEngine* _katana;
|
||||
RoutingLayerGauge* _layerGauge;
|
||||
size_t _depth;
|
||||
Flags _flags;
|
||||
|
|
|
@ -39,18 +39,20 @@ namespace Katana {
|
|||
, Insert = (1<< 3)
|
||||
, Ripup = (1<< 4)
|
||||
, RipedByLocal = (1<< 5)
|
||||
, ResetRipup = (1<< 6)
|
||||
, ToRipupLimit = (1<< 7)
|
||||
, MoveToAxis = (1<< 8)
|
||||
, AxisHint = (1<< 9)
|
||||
, Lock = (1<<10)
|
||||
, PackingMode = (1<<11)
|
||||
, ToState = (1<<12)
|
||||
, EventLevel1 = (1<<13)
|
||||
, EventLevel2 = (1<<14)
|
||||
, EventLevel3 = (1<<15)
|
||||
, EventLevel4 = (1<<16)
|
||||
, EventLevel5 = (1<<17)
|
||||
, DecreaseRipup = (1<< 6)
|
||||
, ResetRipup = (1<< 7)
|
||||
, ToRipupLimit = (1<< 8)
|
||||
, MoveToAxis = (1<< 9)
|
||||
, AxisHint = (1<<10)
|
||||
, Lock = (1<<11)
|
||||
, PackingMode = (1<<12)
|
||||
, ToState = (1<<13)
|
||||
, EventLevel1 = (1<<14)
|
||||
, EventLevel2 = (1<<15)
|
||||
, EventLevel3 = (1<<16)
|
||||
, EventLevel4 = (1<<17)
|
||||
, EventLevel5 = (1<<18)
|
||||
, AllEventLevels = EventLevel1|EventLevel2|EventLevel3|EventLevel4|EventLevel5
|
||||
, SelfLock = Self |Lock
|
||||
, SelfInsert = Self |Insert
|
||||
, SelfRipup = Self |Ripup
|
||||
|
@ -115,6 +117,7 @@ namespace Katana {
|
|||
inline bool isFullBlocked () const;
|
||||
inline bool isSymmetric () const;
|
||||
inline bool isMinimizeDrag () const;
|
||||
inline bool hasAction ( TrackElement* ) const;
|
||||
inline RoutingEvent* getEvent () const;
|
||||
inline RoutingEvent* getEvent1 () const;
|
||||
inline RoutingEvent* getEvent2 () const;
|
||||
|
@ -139,6 +142,8 @@ namespace Katana {
|
|||
inline size_t getEnd ( size_t icost, size_t itrack=0 );
|
||||
inline size_t getEnd1 ( size_t icost, size_t itrack=0 );
|
||||
inline size_t getEnd2 ( size_t icost, size_t itrack=0 );
|
||||
inline DbU::Unit getCandidateAxis1 ( size_t icost ) const;
|
||||
inline DbU::Unit getCandidateAxis2 ( size_t icost ) const;
|
||||
inline vector<SegmentAction>& getActions ();
|
||||
inline void setState ( uint32_t );
|
||||
void setDataState ( uint32_t );
|
||||
|
@ -192,39 +197,47 @@ namespace Katana {
|
|||
};
|
||||
|
||||
|
||||
inline bool SegmentFsm::isMinimizeDrag () const { return _minimizeDrag; }
|
||||
inline bool SegmentFsm::isSymmetric () const { return _event2 != NULL; }
|
||||
inline bool SegmentFsm::isFullBlocked () const { return _fullBlocked and _costs.size(); }
|
||||
inline RoutingEvent* SegmentFsm::getEvent () const { return (_useEvent2) ? _event2 : _event1; }
|
||||
inline RoutingEvent* SegmentFsm::getEvent1 () const { return _event1; }
|
||||
inline RoutingEvent* SegmentFsm::getEvent2 () const { return _event2; }
|
||||
inline RoutingEventQueue& SegmentFsm::getQueue () const { return _queue; }
|
||||
inline RoutingEventHistory& SegmentFsm::getHistory () const { return _history; }
|
||||
inline uint32_t SegmentFsm::getState () const { return _state; }
|
||||
inline TrackElement* SegmentFsm::getSegment1 () const { return _event1->getSegment(); }
|
||||
inline TrackElement* SegmentFsm::getSegment2 () const { return (_event2) ? _event2->getSegment() : NULL; }
|
||||
inline DataNegociate* SegmentFsm::getData () { return (_useEvent2) ? _data2 : _data1; }
|
||||
inline DataNegociate* SegmentFsm::getData1 () { return _data1; }
|
||||
inline DataNegociate* SegmentFsm::getData2 () { return _data2; }
|
||||
inline Interval& SegmentFsm::getConstraint () { return _constraint; }
|
||||
inline Interval& SegmentFsm::getOptimal () { return _optimal; }
|
||||
inline vector<TrackCost*>& SegmentFsm::getCosts () { return _costs; }
|
||||
inline TrackCost* SegmentFsm::getCost ( size_t icost ) { return _costs[icost]; }
|
||||
inline Track* SegmentFsm::getTrack ( size_t icost, size_t itrack ) { return (_useEvent2) ? getTrack2(icost,itrack) : getTrack1(icost,itrack); }
|
||||
inline size_t SegmentFsm::getBegin ( size_t icost, size_t itrack ) { return (_useEvent2) ? getBegin2(icost,itrack) : getBegin1(icost,itrack); }
|
||||
inline size_t SegmentFsm::getEnd ( size_t icost, size_t itrack ) { return (_useEvent2) ? getEnd2 (icost,itrack) : getEnd1 (icost,itrack); }
|
||||
inline Track* SegmentFsm::getTrack1 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::NoFlags ); }
|
||||
inline Track* SegmentFsm::getTrack2 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::Symmetric); }
|
||||
inline size_t SegmentFsm::getBegin1 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::NoFlags ); }
|
||||
inline size_t SegmentFsm::getBegin2 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::Symmetric); }
|
||||
inline size_t SegmentFsm::getEnd1 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::NoFlags ); }
|
||||
inline size_t SegmentFsm::getEnd2 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::Symmetric); }
|
||||
inline vector<SegmentAction>& SegmentFsm::getActions () { return _actions; }
|
||||
inline void SegmentFsm::setState ( uint32_t state ) { _state = state; }
|
||||
inline void SegmentFsm::clearActions () { _actions.clear(); }
|
||||
inline SegmentFsm& SegmentFsm::useEvent1 () { _useEvent2 = false; return *this; }
|
||||
inline SegmentFsm& SegmentFsm::useEvent2 () { _useEvent2 = true ; return *this; }
|
||||
inline bool SegmentFsm::isMinimizeDrag () const { return _minimizeDrag; }
|
||||
inline bool SegmentFsm::isSymmetric () const { return _event2 != NULL; }
|
||||
inline bool SegmentFsm::isFullBlocked () const { return _fullBlocked and _costs.size(); }
|
||||
inline RoutingEvent* SegmentFsm::getEvent () const { return (_useEvent2) ? _event2 : _event1; }
|
||||
inline RoutingEvent* SegmentFsm::getEvent1 () const { return _event1; }
|
||||
inline RoutingEvent* SegmentFsm::getEvent2 () const { return _event2; }
|
||||
inline RoutingEventQueue& SegmentFsm::getQueue () const { return _queue; }
|
||||
inline RoutingEventHistory& SegmentFsm::getHistory () const { return _history; }
|
||||
inline uint32_t SegmentFsm::getState () const { return _state; }
|
||||
inline TrackElement* SegmentFsm::getSegment1 () const { return _event1->getSegment(); }
|
||||
inline TrackElement* SegmentFsm::getSegment2 () const { return (_event2) ? _event2->getSegment() : NULL; }
|
||||
inline DataNegociate* SegmentFsm::getData () { return (_useEvent2) ? _data2 : _data1; }
|
||||
inline DataNegociate* SegmentFsm::getData1 () { return _data1; }
|
||||
inline DataNegociate* SegmentFsm::getData2 () { return _data2; }
|
||||
inline Interval& SegmentFsm::getConstraint () { return _constraint; }
|
||||
inline Interval& SegmentFsm::getOptimal () { return _optimal; }
|
||||
inline vector<TrackCost*>& SegmentFsm::getCosts () { return _costs; }
|
||||
inline TrackCost* SegmentFsm::getCost ( size_t icost ) { return _costs[icost]; }
|
||||
inline Track* SegmentFsm::getTrack ( size_t icost, size_t itrack ) { return (_useEvent2) ? getTrack2(icost,itrack) : getTrack1(icost,itrack); }
|
||||
inline size_t SegmentFsm::getBegin ( size_t icost, size_t itrack ) { return (_useEvent2) ? getBegin2(icost,itrack) : getBegin1(icost,itrack); }
|
||||
inline size_t SegmentFsm::getEnd ( size_t icost, size_t itrack ) { return (_useEvent2) ? getEnd2 (icost,itrack) : getEnd1 (icost,itrack); }
|
||||
inline Track* SegmentFsm::getTrack1 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::NoFlags ); }
|
||||
inline Track* SegmentFsm::getTrack2 ( size_t icost, size_t itrack ) { return _costs[icost]->getTrack(itrack,TrackCost::Symmetric); }
|
||||
inline size_t SegmentFsm::getBegin1 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::NoFlags ); }
|
||||
inline size_t SegmentFsm::getBegin2 ( size_t icost, size_t itrack ) { return _costs[icost]->getBegin(itrack,TrackCost::Symmetric); }
|
||||
inline size_t SegmentFsm::getEnd1 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::NoFlags ); }
|
||||
inline size_t SegmentFsm::getEnd2 ( size_t icost, size_t itrack ) { return _costs[icost]->getEnd (itrack,TrackCost::Symmetric); }
|
||||
inline DbU::Unit SegmentFsm::getCandidateAxis1 ( size_t icost ) const { return _costs[icost]->getRefCandidateAxis(); }
|
||||
inline DbU::Unit SegmentFsm::getCandidateAxis2 ( size_t icost ) const { return _costs[icost]->getSymCandidateAxis(); }
|
||||
inline vector<SegmentAction>& SegmentFsm::getActions () { return _actions; }
|
||||
inline void SegmentFsm::setState ( uint32_t state ) { _state = state; }
|
||||
inline void SegmentFsm::clearActions () { _actions.clear(); }
|
||||
inline SegmentFsm& SegmentFsm::useEvent1 () { _useEvent2 = false; return *this; }
|
||||
inline SegmentFsm& SegmentFsm::useEvent2 () { _useEvent2 = true ; return *this; }
|
||||
|
||||
inline bool SegmentFsm::hasAction ( TrackElement* segment ) const
|
||||
{
|
||||
for ( const SegmentAction& action : _actions )
|
||||
if (action.getSegment() == segment) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Katana namespace.
|
||||
|
||||
|
|
|
@ -65,66 +65,74 @@ namespace Katana {
|
|||
public:
|
||||
typedef Anabatic::Session Super;
|
||||
public:
|
||||
static Session* get ( const char* message=NULL );
|
||||
inline static Super* base ();
|
||||
inline static bool isEmpty ();
|
||||
inline static KatanaEngine* getKatanaEngine ();
|
||||
static Configuration* getConfiguration ();
|
||||
inline static Net* getBlockageNet ();
|
||||
inline static NegociateWindow* getNegociateWindow ();
|
||||
inline static uint32_t getRipupCost ();
|
||||
inline static Anabatic::GCell* getGCellUnder ( DbU::Unit, DbU::Unit );
|
||||
static void setInterrupt ( bool );
|
||||
inline static Interval& toAxisInterval ( Interval&, size_t depth );
|
||||
inline static void addInsertEvent ( TrackMarker* , Track* );
|
||||
inline static void addInsertEvent ( TrackElement* , Track* );
|
||||
inline static void addRemoveEvent ( TrackElement* );
|
||||
inline static void addMoveEvent ( TrackElement* , Track* );
|
||||
inline static void addSortEvent ( Track*, bool forced=false );
|
||||
inline static void addLockEvent ( TrackElement* );
|
||||
inline static size_t revalidate ();
|
||||
static AutoContact* lookup ( Contact* );
|
||||
static TrackElement* lookup ( Segment* );
|
||||
static TrackElement* lookup ( AutoSegment* );
|
||||
static void addShortDogleg ( TrackElement*, TrackElement* );
|
||||
static TrackElement* getDoglegPaired ( TrackElement* );
|
||||
static Session* _open ( KatanaEngine* );
|
||||
private:
|
||||
KatanaEngine* _getKatanaEngine ();
|
||||
Net* _getBlockageNet ();
|
||||
uint32_t _getRipupCost ();
|
||||
Anabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit );
|
||||
Interval& _toAxisInterval ( Interval&, size_t depth ) const;
|
||||
void _doLockEvents ();
|
||||
void _doRemovalEvents ();
|
||||
virtual size_t _revalidate ();
|
||||
bool _isEmpty () const;
|
||||
NegociateWindow* _getNegociateWindow ();
|
||||
void _addInsertEvent ( TrackMarker* , Track* );
|
||||
void _addInsertEvent ( TrackElement* , Track* );
|
||||
void _addRemoveEvent ( TrackElement* );
|
||||
void _addMoveEvent ( TrackElement* , Track* );
|
||||
void _addSortEvent ( Track*, bool forced );
|
||||
void _addLockEvent ( TrackElement* );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual string _getTypeName () const;
|
||||
static Session* get ( const char* message=NULL );
|
||||
inline static Super* base ();
|
||||
inline static bool isEmpty ();
|
||||
inline static KatanaEngine* getKatanaEngine ();
|
||||
static Configuration* getConfiguration ();
|
||||
inline static Net* getBlockageNet ();
|
||||
inline static NegociateWindow* getNegociateWindow ();
|
||||
inline static uint32_t getRipupCost ();
|
||||
inline static Anabatic::GCell* getGCellUnder ( DbU::Unit, DbU::Unit );
|
||||
inline static const std::vector<TrackElement*>&
|
||||
getIndirectInvalids ();
|
||||
static void setInterrupt ( bool );
|
||||
inline static Interval& toAxisInterval ( Interval&, size_t depth );
|
||||
inline static void addIndirectInvalid ( TrackElement* );
|
||||
inline static void addInsertEvent ( TrackMarker* , Track* );
|
||||
inline static void addInsertEvent ( TrackElement* , Track*, DbU::Unit axis );
|
||||
inline static void addRemoveEvent ( TrackElement* );
|
||||
inline static void addMoveEvent ( TrackElement* , Track*, DbU::Unit axis );
|
||||
inline static void addSortEvent ( Track*, bool forced=false );
|
||||
inline static void addLockEvent ( TrackElement* );
|
||||
inline static size_t revalidate ();
|
||||
static AutoContact* lookup ( Contact* );
|
||||
static TrackElement* lookup ( Segment* );
|
||||
static TrackElement* lookup ( AutoSegment* );
|
||||
static void addShortDogleg ( TrackElement*, TrackElement* );
|
||||
static TrackElement* getDoglegPaired ( TrackElement* );
|
||||
static Session* _open ( KatanaEngine* );
|
||||
private:
|
||||
KatanaEngine* _getKatanaEngine ();
|
||||
Net* _getBlockageNet ();
|
||||
uint32_t _getRipupCost ();
|
||||
Anabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit );
|
||||
Interval& _toAxisInterval ( Interval&, size_t depth ) const;
|
||||
void _doLockEvents ();
|
||||
void _doRemovalEvents ( bool reschedule=false );
|
||||
virtual size_t _revalidate ();
|
||||
bool _isEmpty () const;
|
||||
NegociateWindow* _getNegociateWindow ();
|
||||
inline const std::vector<TrackElement*>&
|
||||
_getIndirectInvalids ();
|
||||
inline void _addIndirectInvalid ( TrackElement* );
|
||||
void _addInsertEvent ( TrackMarker* , Track* );
|
||||
void _addInsertEvent ( TrackElement* , Track*, DbU::Unit axis );
|
||||
void _addRemoveEvent ( TrackElement* );
|
||||
void _addMoveEvent ( TrackElement* , Track*, DbU::Unit axis );
|
||||
void _addSortEvent ( Track*, bool forced );
|
||||
void _addLockEvent ( TrackElement* );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual string _getTypeName () const;
|
||||
protected:
|
||||
// Internal Classes.
|
||||
class Event {
|
||||
public:
|
||||
inline Event ( TrackElement*, Track* );
|
||||
inline Event ( TrackElement*, Track*, DbU::Unit );
|
||||
inline Event ( TrackMarker* , Track* );
|
||||
public:
|
||||
TrackElement* _segment;
|
||||
TrackMarker* _marker;
|
||||
Track* _track;
|
||||
DbU::Unit _axis;
|
||||
};
|
||||
protected:
|
||||
// Attributes.
|
||||
vector<Event> _insertEvents;
|
||||
vector<Event> _removeEvents;
|
||||
vector<Event> _lockEvents;
|
||||
set<Track*> _sortEvents;
|
||||
vector<TrackElement*> _indirectInvalids;
|
||||
vector<Event> _insertEvents;
|
||||
vector<Event> _removeEvents;
|
||||
vector<Event> _lockEvents;
|
||||
set<Track*> _sortEvents;
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
Session ( KatanaEngine* );
|
||||
|
@ -138,16 +146,18 @@ namespace Katana {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline Session::Event::Event ( TrackElement* segment , Track* track )
|
||||
inline Session::Event::Event ( TrackElement* segment , Track* track, DbU::Unit axis )
|
||||
: _segment(segment)
|
||||
, _marker (NULL)
|
||||
, _track (track)
|
||||
, _axis (axis)
|
||||
{ }
|
||||
|
||||
inline Session::Event::Event ( TrackMarker* marker , Track* track )
|
||||
: _segment(NULL)
|
||||
, _marker (marker)
|
||||
, _track (track)
|
||||
, _axis (0)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -169,20 +179,26 @@ namespace Katana {
|
|||
inline Anabatic::GCell* Session::getGCellUnder ( DbU::Unit x, DbU::Unit y )
|
||||
{ return get("getGCellUnder()")->_getGCellUnder(x,y); }
|
||||
|
||||
inline const std::vector<TrackElement*>& Session::getIndirectInvalids ()
|
||||
{ return get("getIndirectInvalids()")->_getIndirectInvalids(); }
|
||||
|
||||
inline Interval& Session::toAxisInterval ( Interval& interval, size_t depth )
|
||||
{ return get("getGCellUnder()")->_toAxisInterval(interval,depth); }
|
||||
|
||||
inline void Session::addIndirectInvalid ( TrackElement* element )
|
||||
{ get("addIndirectInvalid(TrackElement*)")->_addIndirectInvalid(element); }
|
||||
|
||||
inline void Session::addInsertEvent ( TrackMarker* marker, Track* track )
|
||||
{ get("addInsertEvent(TrackMarker*)")->_addInsertEvent(marker,track); }
|
||||
|
||||
inline void Session::addInsertEvent ( TrackElement* segment, Track* track )
|
||||
{ get("addInsertEvent(TrackElement*)")->_addInsertEvent(segment,track); }
|
||||
inline void Session::addInsertEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
|
||||
{ get("addInsertEvent(TrackElement*)")->_addInsertEvent(segment,track,axis); }
|
||||
|
||||
inline void Session::addRemoveEvent ( TrackElement* segment )
|
||||
{ get("addRemoveEvent()")->_addRemoveEvent(segment); }
|
||||
|
||||
inline void Session::addMoveEvent ( TrackElement* segment, Track* track )
|
||||
{ get("addMoveEvent()")->_addMoveEvent(segment,track); }
|
||||
inline void Session::addMoveEvent ( TrackElement* segment, Track* track, DbU::Unit axis )
|
||||
{ get("addMoveEvent()")->_addMoveEvent(segment,track,axis); }
|
||||
|
||||
inline void Session::addLockEvent ( TrackElement* segment )
|
||||
{ get("addLockEvent()")->_addLockEvent(segment); }
|
||||
|
@ -196,6 +212,12 @@ namespace Katana {
|
|||
inline bool Session::isEmpty ()
|
||||
{ return get("isEmpty()")->_isEmpty(); }
|
||||
|
||||
inline const std::vector<TrackElement*>& Session::_getIndirectInvalids ()
|
||||
{ return _indirectInvalids; }
|
||||
|
||||
inline void Session::_addIndirectInvalid ( TrackElement* element )
|
||||
{ _indirectInvalids.push_back( element ); }
|
||||
|
||||
|
||||
} // Katana namespace.
|
||||
|
||||
|
|
|
@ -60,9 +60,10 @@ namespace Katana {
|
|||
, RightOverlap = (1 << 15)
|
||||
, OverlapGlobal = (1 << 16)
|
||||
, GlobalEnclosed = (1 << 17)
|
||||
, AtRipupLimit = (1 << 18)
|
||||
, MergeMask = ForGlobal |Blockage|Fixed |Infinite
|
||||
|HardOverlap |Overlap |RightOverlap|LeftOverlap|OverlapGlobal
|
||||
|GlobalEnclosed
|
||||
|GlobalEnclosed |AtRipupLimit
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -80,85 +81,95 @@ namespace Katana {
|
|||
};
|
||||
|
||||
public:
|
||||
TrackCost ( TrackElement* refSegment
|
||||
, TrackElement* symSegment
|
||||
, Track* refTrack
|
||||
, Track* symTrack
|
||||
);
|
||||
~TrackCost ();
|
||||
inline bool isForGlobal () const;
|
||||
inline bool isBlockage () const;
|
||||
inline bool isAnalog () const;
|
||||
inline bool isShortNet () const;
|
||||
inline bool isFixed () const;
|
||||
inline bool isInfinite () const;
|
||||
inline bool isOverlap () const;
|
||||
inline bool isLeftOverlap () const;
|
||||
inline bool isRightOverlap () const;
|
||||
inline bool isHardOverlap () const;
|
||||
inline bool isOverlapGlobal () const;
|
||||
inline bool isGlobalEnclosed () const;
|
||||
bool isFree () const;
|
||||
inline bool isSymmetric () const;
|
||||
inline bool isWide () const;
|
||||
inline uint32_t getFlags () const;
|
||||
inline size_t getSpan () const;
|
||||
inline Net* getNet () const;
|
||||
Net* getNet1 () const;
|
||||
Net* getNet2 () const;
|
||||
inline Track* getTrack () const;
|
||||
inline size_t getBegin () const;
|
||||
inline size_t getEnd () const;
|
||||
inline Track* getTrack ( size_t i ) const;
|
||||
inline size_t getBegin ( size_t i ) const;
|
||||
inline size_t getEnd ( size_t i ) const;
|
||||
inline Track* getTrack ( size_t i, uint32_t flags ) const;
|
||||
size_t getBegin ( size_t i, uint32_t flags ) const;
|
||||
size_t getEnd ( size_t i, uint32_t flags ) const;
|
||||
inline const Interval& getInterval () const;
|
||||
inline const Interval& getInterval1 () const;
|
||||
inline const Interval& getInterval2 () const;
|
||||
inline uint32_t getTerminals () const;
|
||||
inline DbU::Unit getDelta () const;
|
||||
inline DbU::Unit getDeltaPerpand () const;
|
||||
inline DbU::Unit getLongestOverlap () const;
|
||||
inline DbU::Unit getAxisWeight () const;
|
||||
inline int getRipupCount () const;
|
||||
inline uint32_t getDataState () const;
|
||||
inline uint32_t setFlags ( uint32_t );
|
||||
inline void setTrack ( Track*, size_t begin, size_t end );
|
||||
inline void setForGlobal ();
|
||||
inline void setBlockage ();
|
||||
inline void setFixed ();
|
||||
inline void setInfinite ();
|
||||
inline void setOverlap ();
|
||||
inline void setLeftOverlap ();
|
||||
inline void setRightOverlap ();
|
||||
inline void setHardOverlap ();
|
||||
inline void setOverlapGlobal ();
|
||||
inline void setGlobalEnclosed ();
|
||||
inline void incTerminals ( uint32_t );
|
||||
inline void incDelta ( DbU::Unit );
|
||||
inline void incDeltaPerpand ( DbU::Unit );
|
||||
inline void incDeltaShared ( DbU::Unit );
|
||||
inline void incAxisWeight ( DbU::Unit );
|
||||
inline void setLonguestOverlap ( DbU::Unit );
|
||||
inline void mergeRipupCount ( int );
|
||||
inline void mergeDataState ( uint32_t );
|
||||
inline bool selectNextTrack ();
|
||||
inline bool select ( size_t index, uint32_t flags );
|
||||
void consolidate ();
|
||||
void setDistanceToFixed ();
|
||||
Record* _getRecord () const;
|
||||
string _getString () const;
|
||||
inline string _getTypeName () const;
|
||||
private:
|
||||
TrackCost ( const TrackCost& ) = delete;
|
||||
TrackCost& operator= ( const TrackCost& ) = delete;
|
||||
TrackCost ( TrackElement* refSegment
|
||||
, TrackElement* symSegment
|
||||
, Track* refTrack
|
||||
, Track* symTrack
|
||||
, DbU::Unit refCandidateAxis
|
||||
, DbU::Unit symCandidateAxis
|
||||
);
|
||||
~TrackCost ();
|
||||
inline bool isForGlobal () const;
|
||||
inline bool isBlockage () const;
|
||||
inline bool isAnalog () const;
|
||||
inline bool isShortNet () const;
|
||||
inline bool isFixed () const;
|
||||
inline bool isInfinite () const;
|
||||
inline bool isOverlap () const;
|
||||
inline bool isLeftOverlap () const;
|
||||
inline bool isRightOverlap () const;
|
||||
inline bool isHardOverlap () const;
|
||||
inline bool isOverlapGlobal () const;
|
||||
inline bool isGlobalEnclosed () const;
|
||||
inline bool isAtRipupLimit () const;
|
||||
bool isFree () const;
|
||||
inline bool isSymmetric () const;
|
||||
inline bool isWide () const;
|
||||
inline uint32_t getFlags () const;
|
||||
inline size_t getSpan () const;
|
||||
inline Net* getNet () const;
|
||||
Net* getNet1 () const;
|
||||
Net* getNet2 () const;
|
||||
inline TrackElement* getRefElement () const;
|
||||
inline TrackElement* getSymElement () const;
|
||||
inline DbU::Unit getRefCandidateAxis () const;
|
||||
inline DbU::Unit getSymCandidateAxis () const;
|
||||
inline Track* getTrack () const;
|
||||
inline size_t getBegin () const;
|
||||
inline size_t getEnd () const;
|
||||
inline Track* getTrack ( size_t i ) const;
|
||||
inline size_t getBegin ( size_t i ) const;
|
||||
inline size_t getEnd ( size_t i ) const;
|
||||
inline Track* getTrack ( size_t i, uint32_t flags ) const;
|
||||
size_t getBegin ( size_t i, uint32_t flags ) const;
|
||||
size_t getEnd ( size_t i, uint32_t flags ) const;
|
||||
inline const Interval& getInterval () const;
|
||||
inline const Interval& getInterval1 () const;
|
||||
inline const Interval& getInterval2 () const;
|
||||
inline uint32_t getTerminals () const;
|
||||
inline DbU::Unit getDelta () const;
|
||||
inline DbU::Unit getDeltaPerpand () const;
|
||||
inline DbU::Unit getLongestOverlap () const;
|
||||
inline DbU::Unit getAxisWeight () const;
|
||||
inline int getRipupCount () const;
|
||||
inline uint32_t getDataState () const;
|
||||
inline uint32_t setFlags ( uint32_t );
|
||||
inline void setTrack ( Track*, size_t begin, size_t end );
|
||||
inline void setForGlobal ();
|
||||
inline void setBlockage ();
|
||||
inline void setFixed ();
|
||||
inline void setInfinite ();
|
||||
inline void setOverlap ();
|
||||
inline void setLeftOverlap ();
|
||||
inline void setRightOverlap ();
|
||||
inline void setHardOverlap ();
|
||||
inline void setOverlapGlobal ();
|
||||
inline void setGlobalEnclosed ();
|
||||
inline void setAtRipupLimit ();
|
||||
inline void incTerminals ( uint32_t );
|
||||
inline void incDelta ( DbU::Unit );
|
||||
inline void incDeltaPerpand ( DbU::Unit );
|
||||
inline void incDeltaShared ( DbU::Unit );
|
||||
inline void incAxisWeight ( DbU::Unit );
|
||||
inline void setLonguestOverlap ( DbU::Unit );
|
||||
inline void mergeRipupCount ( int );
|
||||
inline void mergeDataState ( uint32_t );
|
||||
inline bool selectNextTrack ();
|
||||
inline bool select ( size_t index, uint32_t flags );
|
||||
void consolidate ();
|
||||
void setDistanceToFixed ();
|
||||
Record* _getRecord () const;
|
||||
string _getString () const;
|
||||
inline string _getTypeName () const;
|
||||
private:
|
||||
TrackCost ( const TrackCost& ) = delete;
|
||||
TrackCost& operator= ( const TrackCost& ) = delete;
|
||||
// Attributes.
|
||||
private:
|
||||
uint32_t _flags;
|
||||
size_t _span;
|
||||
DbU::Unit _refCandidateAxis;
|
||||
DbU::Unit _symCandidateAxis;
|
||||
std::vector< std::tuple<Track*,size_t,size_t> >
|
||||
_tracks;
|
||||
TrackElement* _segment1;
|
||||
|
@ -180,57 +191,63 @@ namespace Katana {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline bool TrackCost::isForGlobal () const { return _flags & ForGlobal; }
|
||||
inline bool TrackCost::isBlockage () const { return _flags & Blockage; }
|
||||
inline bool TrackCost::isAnalog () const { return _flags & Analog; }
|
||||
inline bool TrackCost::isShortNet () const { return _flags & ShortNet; }
|
||||
inline bool TrackCost::isFixed () const { return _flags & Fixed; }
|
||||
inline bool TrackCost::isInfinite () const { return _flags & Infinite; }
|
||||
inline bool TrackCost::isOverlap () const { return _flags & Overlap; }
|
||||
inline bool TrackCost::isLeftOverlap () const { return _flags & LeftOverlap; }
|
||||
inline bool TrackCost::isRightOverlap () const { return _flags & RightOverlap; }
|
||||
inline bool TrackCost::isHardOverlap () const { return _flags & HardOverlap; }
|
||||
inline bool TrackCost::isOverlapGlobal () const { return _flags & OverlapGlobal; }
|
||||
inline bool TrackCost::isGlobalEnclosed () const { return _flags & GlobalEnclosed; }
|
||||
inline bool TrackCost::isSymmetric () const { return _flags & Symmetric; }
|
||||
inline bool TrackCost::isWide () const { return (_span > 1); }
|
||||
inline uint32_t TrackCost::getFlags () const { return _flags; }
|
||||
inline size_t TrackCost::getSpan () const { return _span; }
|
||||
inline Net* TrackCost::getNet () const { return (_selectFlags & Symmetric) ? getNet2() : getNet1(); }
|
||||
inline Track* TrackCost::getTrack ( size_t i ) const { return getTrack(i,NoFlags); }
|
||||
inline size_t TrackCost::getBegin () const { return getBegin(_selectIndex,_selectFlags); }
|
||||
inline size_t TrackCost::getBegin ( size_t i ) const { return getBegin(i,NoFlags); }
|
||||
inline size_t TrackCost::getEnd () const { return getEnd (_selectIndex,_selectFlags); }
|
||||
inline size_t TrackCost::getEnd ( size_t i ) const { return getEnd (i,NoFlags); }
|
||||
inline const Interval& TrackCost::getInterval () const { return (_selectFlags & Symmetric) ? getInterval2() : getInterval1(); }
|
||||
inline const Interval& TrackCost::getInterval1 () const { return _interval1; }
|
||||
inline const Interval& TrackCost::getInterval2 () const { return _interval2; }
|
||||
inline uint32_t TrackCost::getTerminals () const { return _terminals; }
|
||||
inline DbU::Unit TrackCost::getLongestOverlap () const { return _longuestOverlap; }
|
||||
inline DbU::Unit TrackCost::getDelta () const { return _delta; }
|
||||
inline DbU::Unit TrackCost::getAxisWeight () const { return _axisWeight; }
|
||||
inline int TrackCost::getRipupCount () const { return _ripupCount; }
|
||||
inline uint32_t TrackCost::getDataState () const { return _dataState; }
|
||||
inline uint32_t TrackCost::setFlags ( uint32_t mask ) { _flags |= mask; return _flags; }
|
||||
inline void TrackCost::setForGlobal () { _flags |= ForGlobal; }
|
||||
inline void TrackCost::setBlockage () { _flags |= Blockage; }
|
||||
inline void TrackCost::setFixed () { _flags |= Fixed; }
|
||||
inline void TrackCost::setInfinite () { _flags |= Infinite; }
|
||||
inline void TrackCost::setOverlap () { _flags |= Overlap; }
|
||||
inline void TrackCost::setLeftOverlap () { _flags |= LeftOverlap; }
|
||||
inline void TrackCost::setRightOverlap () { _flags |= RightOverlap; }
|
||||
inline void TrackCost::setHardOverlap () { _flags |= HardOverlap; }
|
||||
inline void TrackCost::setOverlapGlobal () { _flags |= OverlapGlobal; }
|
||||
inline void TrackCost::setGlobalEnclosed () { _flags |= GlobalEnclosed; }
|
||||
inline void TrackCost::incTerminals ( uint32_t terminals ) { _terminals += terminals; }
|
||||
inline void TrackCost::incDelta ( DbU::Unit delta ) { _delta += delta; }
|
||||
inline void TrackCost::incDeltaPerpand ( DbU::Unit delta ) { _deltaPerpand += delta; }
|
||||
inline void TrackCost::incDeltaShared ( DbU::Unit delta ) { _deltaShared += delta; }
|
||||
inline void TrackCost::incAxisWeight ( DbU::Unit weight ) { _axisWeight += weight; }
|
||||
inline void TrackCost::setLonguestOverlap ( DbU::Unit overlap ) { _longuestOverlap = std::max( overlap, _longuestOverlap ); }
|
||||
inline void TrackCost::mergeRipupCount ( int count ) { _ripupCount = std::max( count , _ripupCount ); }
|
||||
inline void TrackCost::mergeDataState ( uint32_t state ) { _dataState = std::max( state , _dataState ); }
|
||||
inline string TrackCost::_getTypeName () const { return "TrackCost"; }
|
||||
inline bool TrackCost::isForGlobal () const { return _flags & ForGlobal; }
|
||||
inline bool TrackCost::isBlockage () const { return _flags & Blockage; }
|
||||
inline bool TrackCost::isAnalog () const { return _flags & Analog; }
|
||||
inline bool TrackCost::isShortNet () const { return _flags & ShortNet; }
|
||||
inline bool TrackCost::isFixed () const { return _flags & Fixed; }
|
||||
inline bool TrackCost::isInfinite () const { return _flags & Infinite; }
|
||||
inline bool TrackCost::isOverlap () const { return _flags & Overlap; }
|
||||
inline bool TrackCost::isLeftOverlap () const { return _flags & LeftOverlap; }
|
||||
inline bool TrackCost::isRightOverlap () const { return _flags & RightOverlap; }
|
||||
inline bool TrackCost::isHardOverlap () const { return _flags & HardOverlap; }
|
||||
inline bool TrackCost::isOverlapGlobal () const { return _flags & OverlapGlobal; }
|
||||
inline bool TrackCost::isGlobalEnclosed () const { return _flags & GlobalEnclosed; }
|
||||
inline bool TrackCost::isAtRipupLimit () const { return _flags & AtRipupLimit; }
|
||||
inline bool TrackCost::isSymmetric () const { return _flags & Symmetric; }
|
||||
inline bool TrackCost::isWide () const { return (_span > 1); }
|
||||
inline uint32_t TrackCost::getFlags () const { return _flags; }
|
||||
inline size_t TrackCost::getSpan () const { return _span; }
|
||||
inline Net* TrackCost::getNet () const { return (_selectFlags & Symmetric) ? getNet2() : getNet1(); }
|
||||
inline TrackElement* TrackCost::getRefElement () const { return _segment1; }
|
||||
inline TrackElement* TrackCost::getSymElement () const { return _segment2; }
|
||||
inline DbU::Unit TrackCost::getRefCandidateAxis () const { return _refCandidateAxis; }
|
||||
inline DbU::Unit TrackCost::getSymCandidateAxis () const { return _symCandidateAxis; }
|
||||
inline Track* TrackCost::getTrack ( size_t i ) const { return getTrack(i,NoFlags); }
|
||||
inline size_t TrackCost::getBegin () const { return getBegin(_selectIndex,_selectFlags); }
|
||||
inline size_t TrackCost::getBegin ( size_t i ) const { return getBegin(i,NoFlags); }
|
||||
inline size_t TrackCost::getEnd () const { return getEnd (_selectIndex,_selectFlags); }
|
||||
inline size_t TrackCost::getEnd ( size_t i ) const { return getEnd (i,NoFlags); }
|
||||
inline const Interval& TrackCost::getInterval () const { return (_selectFlags & Symmetric) ? getInterval2() : getInterval1(); }
|
||||
inline const Interval& TrackCost::getInterval1 () const { return _interval1; }
|
||||
inline const Interval& TrackCost::getInterval2 () const { return _interval2; }
|
||||
inline uint32_t TrackCost::getTerminals () const { return _terminals; }
|
||||
inline DbU::Unit TrackCost::getLongestOverlap () const { return _longuestOverlap; }
|
||||
inline DbU::Unit TrackCost::getDelta () const { return _delta; }
|
||||
inline DbU::Unit TrackCost::getAxisWeight () const { return _axisWeight; }
|
||||
inline int TrackCost::getRipupCount () const { return _ripupCount; }
|
||||
inline uint32_t TrackCost::getDataState () const { return _dataState; }
|
||||
inline uint32_t TrackCost::setFlags ( uint32_t mask ) { _flags |= mask; return _flags; }
|
||||
inline void TrackCost::setForGlobal () { _flags |= ForGlobal; }
|
||||
inline void TrackCost::setBlockage () { _flags |= Blockage; }
|
||||
inline void TrackCost::setFixed () { _flags |= Fixed; }
|
||||
inline void TrackCost::setInfinite () { _flags |= Infinite; }
|
||||
inline void TrackCost::setOverlap () { _flags |= Overlap; }
|
||||
inline void TrackCost::setLeftOverlap () { _flags |= LeftOverlap; }
|
||||
inline void TrackCost::setRightOverlap () { _flags |= RightOverlap; }
|
||||
inline void TrackCost::setHardOverlap () { _flags |= HardOverlap; }
|
||||
inline void TrackCost::setOverlapGlobal () { _flags |= OverlapGlobal; }
|
||||
inline void TrackCost::setGlobalEnclosed () { _flags |= GlobalEnclosed; }
|
||||
inline void TrackCost::setAtRipupLimit () { _flags |= AtRipupLimit; }
|
||||
inline void TrackCost::incTerminals ( uint32_t terminals ) { _terminals += terminals; }
|
||||
inline void TrackCost::incDelta ( DbU::Unit delta ) { _delta += delta; }
|
||||
inline void TrackCost::incDeltaPerpand ( DbU::Unit delta ) { _deltaPerpand += delta; }
|
||||
inline void TrackCost::incDeltaShared ( DbU::Unit delta ) { _deltaShared += delta; }
|
||||
inline void TrackCost::incAxisWeight ( DbU::Unit weight ) { _axisWeight += weight; }
|
||||
inline void TrackCost::setLonguestOverlap ( DbU::Unit overlap ) { _longuestOverlap = std::max( overlap, _longuestOverlap ); }
|
||||
inline void TrackCost::mergeRipupCount ( int count ) { _ripupCount = std::max( count , _ripupCount ); }
|
||||
inline void TrackCost::mergeDataState ( uint32_t state ) { _dataState = std::max( state , _dataState ); }
|
||||
inline string TrackCost::_getTypeName () const { return "TrackCost"; }
|
||||
|
||||
|
||||
inline TrackCost::Compare::Compare ( uint32_t flags ) : _flags(flags) { }
|
||||
|
@ -238,8 +255,8 @@ namespace Katana {
|
|||
|
||||
inline Track* TrackCost::getTrack () const
|
||||
{
|
||||
cdebug_log( 55,0) << "TrackCost::getTrack() _index:" << _selectIndex
|
||||
<< " flags:" << _selectFlags << std::endl;
|
||||
// cdebug_log( 55,0) << "TrackCost::getTrack() _index:" << _selectIndex
|
||||
// << " flags:" << _selectFlags << std::endl;
|
||||
return getTrack(_selectIndex,_selectFlags);
|
||||
}
|
||||
|
||||
|
@ -278,9 +295,9 @@ namespace Katana {
|
|||
{
|
||||
if (i >= _span) return NULL;
|
||||
|
||||
cdebug_log( 55,0) << "TrackCost::getTrack() i:" << i
|
||||
<< " flags:" << flags
|
||||
<< " index:" << (i + ((flags & Symmetric) ? _span : 0)) << std::endl;
|
||||
// cdebug_log( 55,0) << "TrackCost::getTrack() i:" << i
|
||||
// << " flags:" << flags
|
||||
// << " index:" << (i + ((flags & Symmetric) ? _span : 0)) << std::endl;
|
||||
|
||||
return std::get<0>( _tracks[i + ((flags & Symmetric) ? _span : 0)] );
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ namespace Katana {
|
|||
// Class : "TrackElement".
|
||||
|
||||
enum TrackElementFlags { TElemCreated = (1 << 0)
|
||||
, TElemBlockage = (1 << 1)
|
||||
, TElemFixed = (1 << 2)
|
||||
, TElemBlockage = (1 << 2)
|
||||
, TElemFixed = (1 << 3)
|
||||
, TElemLocked = (1 << 4)
|
||||
, TElemRouted = (1 << 5)
|
||||
, TElemShortDogleg = (1 << 6)
|
||||
|
@ -106,6 +106,8 @@ namespace Katana {
|
|||
virtual bool isHorizontal () const = 0;
|
||||
virtual bool isVertical () const = 0;
|
||||
virtual bool isWide () const;
|
||||
virtual bool isNonPref () const;
|
||||
virtual bool isUnbreakable () const;
|
||||
virtual bool isLocal () const;
|
||||
virtual bool isGlobal () const;
|
||||
virtual bool isBipoint () const;
|
||||
|
@ -171,7 +173,7 @@ namespace Katana {
|
|||
virtual Interval getSourceConstraints () const;
|
||||
virtual Interval getTargetConstraints () const;
|
||||
virtual DataNegociate* getDataNegociate ( Flags flags=Flags::DataSelf ) const;
|
||||
virtual TrackElement* getCanonical ( Interval& );
|
||||
inline TrackElement* getCanonical ( Interval& );
|
||||
virtual size_t getGCells ( vector<GCell*>& ) const;
|
||||
virtual TrackElement* getParent () const;
|
||||
virtual uint32_t getDoglegLevel () const;
|
||||
|
@ -194,11 +196,12 @@ namespace Katana {
|
|||
virtual void setDoglegLevel ( uint32_t );
|
||||
virtual void swapTrack ( TrackElement* );
|
||||
virtual void reschedule ( uint32_t level );
|
||||
virtual void detach ();
|
||||
//virtual void detach ();
|
||||
virtual void detach ( std::set<Track*>& );
|
||||
virtual void invalidate ();
|
||||
virtual void revalidate ();
|
||||
virtual void updatePPitch ();
|
||||
virtual void updateTrackSpan ();
|
||||
virtual void addTrackCount ( int32_t );
|
||||
virtual void incOverlapCost ( TrackCost& ) const;
|
||||
virtual void setAxis ( DbU::Unit, uint32_t flags=Anabatic::AutoSegment::SegAxisSet );
|
||||
|
@ -258,6 +261,7 @@ namespace Katana {
|
|||
inline DbU::Unit TrackElement::getLength () const { return getTargetU() - getSourceU(); }
|
||||
inline DbU::Unit TrackElement::getSourceU () const { return _sourceU; }
|
||||
inline DbU::Unit TrackElement::getTargetU () const { return _targetU; }
|
||||
inline TrackElement* TrackElement::getCanonical ( Interval& i ) { i=Interval(getSourceU(),getTargetU()); return this; }
|
||||
inline Interval TrackElement::getCanonicalInterval () const { return Interval(getSourceU(),getTargetU()); }
|
||||
inline DbU::Unit TrackElement::getSymmetricAxis ( DbU::Unit axis ) const { return axis - (getTrackSpan()-1)*getPitch(); }
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace Katana {
|
|||
virtual bool isDrag () const;
|
||||
virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
|
||||
virtual bool isStrap () const;
|
||||
virtual bool isUnbreakable () const;
|
||||
virtual bool isSlackened () const;
|
||||
virtual bool isDogleg () const;
|
||||
virtual bool isShortDogleg () const;
|
||||
|
@ -115,7 +116,6 @@ namespace Katana {
|
|||
virtual Interval getSourceConstraints () const;
|
||||
virtual Interval getTargetConstraints () const;
|
||||
virtual DataNegociate* getDataNegociate ( Flags flags=Flags::DataSelf ) const;
|
||||
virtual TrackElement* getCanonical ( Interval& );
|
||||
virtual size_t getGCells ( vector<GCell*>& ) const;
|
||||
virtual TrackElement* getSourceDogleg ();
|
||||
virtual TrackElement* getTargetDogleg ();
|
||||
|
@ -133,7 +133,7 @@ namespace Katana {
|
|||
virtual void setDoglegLevel ( uint32_t );
|
||||
virtual void swapTrack ( TrackElement* );
|
||||
virtual void reschedule ( uint32_t level );
|
||||
virtual void detach ();
|
||||
//virtual void detach ();
|
||||
virtual void detach ( std::set<Track*>& );
|
||||
virtual void invalidate ();
|
||||
virtual void revalidate ();
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Universite 2019-2019, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | K i t e - D e t a i l e d R o u t e r |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./katana/TrackSegmentNonPref.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef KATANA_TRACK_SEGMENT_NON_PREF_H
|
||||
#define KATANA_TRACK_SEGMENT_NON_PREF_H
|
||||
|
||||
#include <set>
|
||||
#include <functional>
|
||||
#include "katana/TrackSegment.h"
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::binary_function;
|
||||
using Hurricane::Record;
|
||||
using Hurricane::Interval;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Layer;
|
||||
using Anabatic::AutoSegment;
|
||||
|
||||
class DataNegociate;
|
||||
class Track;
|
||||
class TrackCost;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "TrackSegmentNonPref".
|
||||
|
||||
class TrackSegmentNonPref : public TrackSegment {
|
||||
friend class TrackSegment;
|
||||
public:
|
||||
typedef TrackSegment Super;
|
||||
protected:
|
||||
TrackSegmentNonPref ( AutoSegment* ) ;
|
||||
virtual ~TrackSegmentNonPref ();
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
virtual bool isNonPref () const;
|
||||
virtual size_t getTrackSpan () const;
|
||||
virtual uint32_t getTrackCount () const;
|
||||
virtual void addOverlapCost ( TrackCost& ) const;
|
||||
virtual void addTrackCount ( int32_t );
|
||||
virtual void updateTrackSpan ();
|
||||
virtual void invalidate ();
|
||||
private:
|
||||
TrackSegmentNonPref ( const TrackSegmentNonPref& ) = delete;
|
||||
TrackSegmentNonPref& operator= ( const TrackSegmentNonPref& ) = delete;
|
||||
private:
|
||||
size_t _trackSpan;
|
||||
uint32_t _trackCount;
|
||||
};
|
||||
|
||||
|
||||
} // Katana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Katana::TrackSegmentNonPref);
|
||||
|
||||
#endif // KATANA_TRACK_SEGMENT_WIDE_H
|
|
@ -1,11 +1,10 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "vlsisapd/configuration/Configuration.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Box.h"
|
||||
|
||||
#include "crlcore/AllianceFramework.h"
|
||||
#include "crlcore/CellGauge.h"
|
||||
|
||||
#include "knik/Graph.h"
|
||||
#include "knik/MatrixVertex.h"
|
||||
#include "knik/KnikEngine.h"
|
||||
|
@ -142,10 +141,13 @@ Vertex* MatrixVertex::createRegularMatrix ()
|
|||
if ( _xInit || _yInit )
|
||||
throw Error ("MatrixVertex::createRegularMatrix(): cannot initialize matrix twice.");
|
||||
|
||||
string gaugeName = Cfg::getParamString("katabatic.routingGauge","sxlib")->asString();
|
||||
|
||||
Cell* cell = _routingGraph->getCell();
|
||||
DbU::Unit sliceHeight = AllianceFramework::get()->getCellGauge()->getSliceHeight();
|
||||
DbU::Unit cellWidth = cell->getAbutmentBox().getWidth();
|
||||
DbU::Unit cellHeight = cell->getAbutmentBox().getHeight();
|
||||
DbU::Unit sliceHeight = AllianceFramework::get()->getCellGauge(gaugeName)->getSliceHeight();
|
||||
DbU::Unit cellWidth = cell->getAbutmentBox().getWidth();
|
||||
DbU::Unit cellHeight = cell->getAbutmentBox().getHeight();
|
||||
|
||||
_boundingBox = cell->getAbutmentBox();
|
||||
_nbXTiles = (unsigned int)ceil(float(cellWidth) / float(sliceHeight));
|
||||
_nbYTiles = (unsigned int)ceil(float(cellHeight) / float(sliceHeight));
|
||||
|
|
Loading…
Reference in New Issue