Improved management of AutoContactTerminal for VH gauges (real ones).
* New: In Anabatic & Katana, add the new "drag" feature. With VH gauges used by real technologies (M1-H, M2-V, M3-H) a new routing configuration that was not efficiently handled did appear. While the preferred routing direction for metal1 is officially horizontal, due to the way the standard cell must be designed, their metal1 terminals are still verticals (or punctuals). Thus, when connecting to them, we face the case where the metal1 terminal (RoutingPad) is vertical *and* the metal2 wire is also vertical. With that setup, the position of the AutoContactTerminal via12 cannot be deduced, it may range all the way over the metal1 RoutingPad. What may define it's position is the metal3 the metal2 finally connects to. That, is, when we have one horizontal (the metal3) and one vertical (the metal1 RoutingPad). The intermediate wire of metal2 can be kept to a minimum size by "dragging" the via12 close to the via23 when the metal3 wire is moved. * New: In Anabatic & Katana, problem of closely vertically aligneds RoutingPads in metal1 is managed first in PreProcess by restricting the span of the connecteds metal3 and in _makeDogleg also by restricting the span even more tightly (to the RoutingPad itself). * New: In Anabatic::AutoContactTerminal, add the "drag" support. Automatically check if the connecting segment is in the same direction as the RoutingPad, if so, sets the "SegDrag" flag. The dragging state can be known with the "::canDrag()" predicate. * New: In Anabatic::AutoHorizontal, add the "drag" support. The drag state can be known with the "::isDrag()" predicate. In "::_makeDogleg()", when making a dogleg on a dragable segment pass the drag state correctly and restrict the perpandicular span of the perpandicular to the RoutingPad (though segment user constraints). If we make a dogleg on the metal2 is it likely than we cannot go straigth out vertically from the RoutingPad, so the new perpandicular *is* restricted to the RoutingPad span. Idem for AutoVertical. * New: In Katana::Manipulator, add method "::dragMinimize()" which find a hole where to minimize a draggable segment. We finally did not use it, but keep it for potential further use. * New: In Katana::PreProcess, adds a "protectAlignedaccesses()" local function to check for vertically aligned metal1 RoutingPads, in that case setup user constraints on the metal3 segments so they cannot completly cover the other RoutingPad with metal2. We also keep a "metal2protect()" function that create a fixed segment to lock/protect a RoutingPad. Not used for now. * New: In Katana::Session, add a RoutingPad locking event mechanism. This allows us to request the creation of a locking (fixed segment) over a draggable segment. Not used for now. Lock events are processeds before all others as they create new TrackElements. * New: In Katana::Track, "::getNextFree()" and "::getPreviousFree()" method to find the nearest free interval in a Track after/before a position. * Bug: In Anabatic::AutoHorizontal::getConstraints(), merge with user constraints *only* if it's not an empty interval (as we use min/max functions). Idem for AutoVertical. * Bug: In AutoSegments_OnContacts::Locator::isValid(), the boolean test must be inverted. Seems it never worked, but we never used it until now...
This commit is contained in:
parent
19bdba0fcb
commit
7bcf47212b
|
@ -628,6 +628,7 @@ namespace Anabatic {
|
|||
//s.insert( 4, getString(_id) );
|
||||
s.insert( s.size()-1, (isFixed ())?" F":" -" );
|
||||
s.insert( s.size()-1, (isTerminal ())? "T": "-" );
|
||||
s.insert( s.size()-1, (canDrag ())? "D": "-" );
|
||||
s.insert( s.size()-1, (isHTee ())? "h": "-" );
|
||||
s.insert( s.size()-1, (isVTee ())? "v": "-" );
|
||||
s.insert( s.size()-1, (isInvalidated ())? "i": "-" );
|
||||
|
|
|
@ -198,13 +198,18 @@ namespace Anabatic {
|
|||
} else if ( (routingPad = dynamic_cast<RoutingPad*>(component)) ) {
|
||||
Occurrence occurrence = routingPad->getOccurrence();
|
||||
Transformation transformation = occurrence.getPath().getTransformation();
|
||||
Segment* segment = dynamic_cast<Segment*>( occurrence.getEntity() );
|
||||
Horizontal* horizontal = dynamic_cast<Horizontal*>( occurrence.getEntity() );
|
||||
Vertical* vertical = dynamic_cast<Vertical* >( occurrence.getEntity() );
|
||||
|
||||
cdebug_log(145,0) << "Anchor: " << occurrence.getEntity() << endl;
|
||||
cdebug_log(145,0) << "transf: " << transformation << endl;
|
||||
|
||||
if (segment) {
|
||||
Box bb = segment->getBoundingBox();
|
||||
if (horizontal or vertical) {
|
||||
Box bb;
|
||||
// Assume that transformation contains no rotations (for now).
|
||||
if (horizontal) { bb = horizontal->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnHorizontal ); }
|
||||
if (vertical) { bb = vertical ->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnVertical ); }
|
||||
|
||||
transformation.applyOn( bb );
|
||||
xMin = bb.getXMin();
|
||||
yMin = bb.getYMin();
|
||||
|
@ -295,21 +300,40 @@ namespace Anabatic {
|
|||
if (_segment == segment) {
|
||||
_segment = NULL;
|
||||
setFlags( CntInvalidatedCache );
|
||||
unsetFlags( CntDrag );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AutoContactTerminal::cacheAttach ( AutoSegment* segment )
|
||||
{
|
||||
DebugSession::open( getNet(), 140, 150 );
|
||||
|
||||
cdebug_log(145,1) << _getTypeName() << "::cacheAttach() " << this << endl;
|
||||
|
||||
if (_segment) {
|
||||
cerr << Bug( "%s::cacheAttach() On %s,\n"
|
||||
" cache has not been cleared first, cancelled."
|
||||
, _getTypeName().c_str(), getString(this).c_str()
|
||||
) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
DebugSession::close();
|
||||
return;
|
||||
}
|
||||
_segment = segment;
|
||||
unsetFlags( CntInvalidatedCache );
|
||||
|
||||
if ( (dynamic_cast<AutoHorizontal*>(_segment) and (getFlags() & CntOnHorizontal))
|
||||
or (dynamic_cast<AutoVertical*> (_segment) and (getFlags() & CntOnVertical )) ) {
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
setFlags( CntDrag );
|
||||
|
||||
cdebug_log(145,0) << "Drag Contact/Segment set" << endl;
|
||||
}
|
||||
|
||||
cdebug_log(145,0) << "Cached:" << _segment << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
DebugSession::close();
|
||||
}
|
||||
|
||||
|
||||
|
@ -338,8 +362,16 @@ namespace Anabatic {
|
|||
}
|
||||
if (horizontals[0] != NULL ) {
|
||||
_segment = Session::lookup( horizontals[0] );
|
||||
if (getFlags() & CntOnHorizontal) {
|
||||
setFlags( CntDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
}
|
||||
} else {
|
||||
_segment = Session::lookup( verticals[0] );
|
||||
if (getFlags() & CntOnVertical) {
|
||||
setFlags( CntDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
}
|
||||
}
|
||||
if (_segment == NULL) {
|
||||
ostringstream os;
|
||||
|
@ -418,6 +450,18 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "Contact for wide segment." << endl;
|
||||
}
|
||||
|
||||
if (canDrag()) {
|
||||
AutoContact* opposite = _segment->getOppositeAnchor(this);
|
||||
AutoSegment* perpandicular = opposite->getPerpandicular( _segment );
|
||||
if (perpandicular) {
|
||||
DbU::Unit y = perpandicular->getAxis();
|
||||
y = std::min( y, getCBYMax() );
|
||||
y = std::max( y, getCBYMin() );
|
||||
setY( y );
|
||||
cdebug_log(145,0) << "Draging to Y @" << DbU::getValueString(y) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (not getUConstraints(Flags::Horizontal).contains(axis)) {
|
||||
cdebug_log(145,0) << "Cached: " << _segment << endl;
|
||||
message << "Terminal vertical segment X " << DbU::getValueString(axis)
|
||||
|
|
|
@ -142,40 +142,58 @@ namespace Anabatic {
|
|||
|
||||
bool AutoHorizontal::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
|
||||
{
|
||||
cdebug_log(155,1) << "getConstraints() " << this << endl;
|
||||
|
||||
constraintMin = getNativeMin();
|
||||
constraintMax = getNativeMax();
|
||||
|
||||
cdebug_log(144,0) << "Native constraints: ["
|
||||
cdebug_log(155,0) << "Native constraints: ["
|
||||
<< DbU::getValueString(constraintMin) << ":"
|
||||
<< DbU::getValueString(constraintMax) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getAutoSource()->getCBYMin() );
|
||||
constraintMax = std::min ( constraintMax, getAutoSource()->getCBYMax() );
|
||||
cdebug_log(144,0) << "Merge with source constraints: ["
|
||||
cdebug_log(155,0) << "Merge with source constraints: ["
|
||||
<< DbU::getValueString(getAutoSource()->getCBYMin()) << ":"
|
||||
<< DbU::getValueString(getAutoSource()->getCBYMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBYMin() );
|
||||
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBYMax() );
|
||||
cdebug_log(144,0) << "Merge with target constraints: ["
|
||||
cdebug_log(155,0) << "Merge with target constraints: ["
|
||||
<< DbU::getValueString(getAutoTarget()->getCBYMin()) << ":"
|
||||
<< DbU::getValueString(getAutoTarget()->getCBYMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getUserConstraints().getVMin() );
|
||||
constraintMax = std::min ( constraintMax, getUserConstraints().getVMax() );
|
||||
cdebug_log(144,0) << "Merge with user constraints: ["
|
||||
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
|
||||
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
|
||||
<< endl;
|
||||
Interval userConstraints = getUserConstraints();
|
||||
if (not userConstraints.isEmpty()) {
|
||||
constraintMin = std::max ( constraintMin, userConstraints.getVMin() );
|
||||
constraintMax = std::min ( constraintMax, userConstraints.getVMax() );
|
||||
|
||||
cdebug_log(145,0) << "Resulting constraints: " << " ["
|
||||
cdebug_log(155,0) << "Merge with user constraints: ["
|
||||
<< DbU::getValueString(userConstraints.getVMin()) << ":"
|
||||
<< DbU::getValueString(userConstraints.getVMax()) << "]"
|
||||
<< endl;
|
||||
} else
|
||||
cdebug_log(155,0) << "Empty user constraints" << endl;
|
||||
|
||||
cdebug_log(155,0) << "Resulting constraints: ["
|
||||
<< DbU::getValueString(constraintMin) << ":"
|
||||
<< DbU::getValueString(constraintMax) << "]"
|
||||
<< endl;
|
||||
|
||||
if (constraintMin > constraintMax)
|
||||
cerr << Error( "AutoHorizontal::getConstraints(): Invalid interval [%s : %s] -> [%d : %d]\n"
|
||||
" on %s"
|
||||
, DbU::getValueString(constraintMin).c_str()
|
||||
, DbU::getValueString(constraintMax).c_str()
|
||||
, constraintMin
|
||||
, constraintMax
|
||||
, getString(this).c_str()
|
||||
) << endl;
|
||||
|
||||
cdebug_tabw(155,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -753,6 +771,8 @@ namespace Anabatic {
|
|||
GCell* begin = autoSource->getGCell();
|
||||
GCell* end = autoTarget->getGCell();
|
||||
|
||||
if (not autoSource->canDrag()) unsetFlags( SegDrag );
|
||||
|
||||
DbU::Unit doglegAxis = (doglegGCell->getXMax() + doglegGCell->getXMin()) / 2;
|
||||
if (isLocal())
|
||||
doglegAxis = (getSourceX() + getTargetX()) / 2;
|
||||
|
@ -839,6 +859,13 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if (autoTarget->canDrag()) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl;
|
||||
}
|
||||
|
||||
cdebug_tabw(149,-1);
|
||||
DebugSession::close();
|
||||
|
||||
|
|
|
@ -491,13 +491,21 @@ namespace Anabatic {
|
|||
void AutoSegment::invalidate ( Flags flags )
|
||||
{
|
||||
if (Session::doDestroyTool()) return;
|
||||
if (flags & Flags::Source) setFlags( SegInvalidatedSource );
|
||||
if (flags & Flags::Target) setFlags( SegInvalidatedTarget );
|
||||
if (isInvalidated()) return;
|
||||
|
||||
cdebug_log(149,0) << "AutoSegment::invalidate() " << flags << " " << this << endl;
|
||||
cdebug_tabw(149,1);
|
||||
|
||||
if (flags & Flags::Source) setFlags( SegInvalidatedSource );
|
||||
if (flags & Flags::Target) setFlags( SegInvalidatedTarget );
|
||||
|
||||
if ( (getFlags() & SegSourceTerminal) and getAutoSource() and getAutoSource()->canDrag() )
|
||||
getAutoSource()->invalidate();
|
||||
|
||||
if ( (getFlags() & SegTargetTerminal) and getAutoTarget() and getAutoTarget()->canDrag() )
|
||||
getAutoTarget()->invalidate();
|
||||
|
||||
if (isInvalidated()) { cdebug_tabw(149,-1); return; }
|
||||
|
||||
_invalidate();
|
||||
|
||||
if ((flags & Flags::Propagate) and not isNotAligned()) {
|
||||
|
@ -2108,6 +2116,17 @@ namespace Anabatic {
|
|||
coherency = checkConstraints() and coherency;
|
||||
coherency = checkDepthSpin() and coherency;
|
||||
|
||||
if (isDrag() xor (getAutoSource()->canDrag() or getAutoTarget()->canDrag())) {
|
||||
cerr << Error( "%s\n"
|
||||
" Discrepency between segment \"drag\" state and it's contacts.\n"
|
||||
" source:%s\n"
|
||||
" target:%s"
|
||||
, getString(this).c_str()
|
||||
, getString(getAutoSource()).c_str()
|
||||
, getString(getAutoTarget()).c_str()
|
||||
) << endl;
|
||||
coherency = false;
|
||||
}
|
||||
return coherency;
|
||||
}
|
||||
|
||||
|
@ -2123,6 +2142,7 @@ namespace Anabatic {
|
|||
state += isWeakGlobal () ? "g": "-";
|
||||
state += isLongLocal () ? "L": "-";
|
||||
state += isStrongTerminal () ? "T": "-";
|
||||
state += isDrag () ? "D": "-";
|
||||
state += isWeakTerminal1 () ? "W": "-";
|
||||
state += isWeakTerminal2 () ? "w": "-";
|
||||
state += isNotAligned () ? "A": "-";
|
||||
|
@ -2293,6 +2313,7 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
if (wPitch > 1) segment->setFlags( SegWide );
|
||||
if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag );
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
@ -2383,6 +2404,7 @@ namespace Anabatic {
|
|||
throw Error( badSegment, getString(source).c_str(), getString(target).c_str() );
|
||||
|
||||
if (wPitch > 1) segment->setFlags( SegWide );
|
||||
if (source->canDrag() or target->canDrag()) segment->setFlags( SegDrag );
|
||||
|
||||
return segment;
|
||||
}
|
||||
|
|
|
@ -93,14 +93,12 @@ namespace Anabatic {
|
|||
|
||||
|
||||
bool AutoSegments_OnContact::Locator::isValid () const
|
||||
{ return !_hook; }
|
||||
{ return _hook; }
|
||||
|
||||
|
||||
void AutoSegments_OnContact::Locator::progress ()
|
||||
{
|
||||
cdebug_log(145,0) << "AutoSegments_OnContact::Locator::progress()" << endl;
|
||||
|
||||
while (_hook and not _hook->isMaster()) {
|
||||
while (_hook) {
|
||||
_hook = _hook->getNextHook();
|
||||
_element = NULL;
|
||||
|
||||
|
@ -108,7 +106,6 @@ namespace Anabatic {
|
|||
|
||||
Segment* segment = dynamic_cast<Segment*>( _hook->getComponent() );
|
||||
if (segment) _element = Session::lookup( segment );
|
||||
|
||||
if (not _element or (_element == _master)) continue;
|
||||
|
||||
break;
|
||||
|
|
|
@ -137,6 +137,8 @@ namespace Anabatic {
|
|||
|
||||
bool AutoVertical::getConstraints ( DbU::Unit& constraintMin, DbU::Unit& constraintMax ) const
|
||||
{
|
||||
cdebug_log(149,1) << "getConstraints() " << this << endl;
|
||||
|
||||
constraintMin = getNativeMin();
|
||||
constraintMax = getNativeMax();
|
||||
|
||||
|
@ -159,19 +161,32 @@ namespace Anabatic {
|
|||
<< DbU::getValueString(getAutoTarget()->getCBXMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = max ( constraintMin, getUserConstraints().getVMin() );
|
||||
constraintMax = min ( constraintMax, getUserConstraints().getVMax() );
|
||||
Interval userConstraints = getUserConstraints();
|
||||
if (not userConstraints.isEmpty()) {
|
||||
constraintMin = max ( constraintMin, userConstraints.getVMin() );
|
||||
constraintMax = min ( constraintMax, userConstraints.getVMax() );
|
||||
|
||||
cdebug_log(149,0) << "Merge with user constraints: ["
|
||||
<< DbU::getValueString(getUserConstraints().getVMin()) << ":"
|
||||
<< DbU::getValueString(getUserConstraints().getVMax()) << "]"
|
||||
<< endl;
|
||||
cdebug_log(149,0) << "Merge with user constraints: ["
|
||||
<< DbU::getValueString(userConstraints.getVMin()) << ":"
|
||||
<< DbU::getValueString(userConstraints.getVMax()) << "]"
|
||||
<< endl;
|
||||
} else
|
||||
cdebug_log(155,0) << "Empty user constraints" << endl;
|
||||
|
||||
cdebug_log(149,0) << "Resulting constraints: " << " ["
|
||||
cdebug_log(149,0) << "Resulting constraints: ["
|
||||
<< DbU::getValueString(constraintMin) << ":"
|
||||
<< DbU::getValueString(constraintMax) << "]"
|
||||
<< endl;
|
||||
|
||||
if (constraintMin > constraintMax)
|
||||
cerr << Error( "AutoVertical::getConstraints(): Invalid interval [%s : %s]\n"
|
||||
" on %s"
|
||||
, DbU::getValueString(constraintMin).c_str()
|
||||
, DbU::getValueString(constraintMax).c_str()
|
||||
, getString(this).c_str()
|
||||
) << endl;
|
||||
|
||||
cdebug_tabw(149,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -659,12 +674,14 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(149,0) << "AutoVertical::_makeDogleg(GCell*)" << endl;
|
||||
|
||||
//Session::doglegReset();
|
||||
|
||||
AutoContact* autoSource = getAutoSource();
|
||||
AutoContact* autoTarget = getAutoTarget();
|
||||
GCell* begin = autoSource->getGCell();
|
||||
GCell* end = autoTarget->getGCell();
|
||||
|
||||
//Session::doglegReset();
|
||||
if (not autoSource->canDrag()) unsetFlags( SegDrag );
|
||||
|
||||
DbU::Unit doglegAxis = (doglegGCell->getYMax() + doglegGCell->getYMin()) / 2;
|
||||
if (isLocal())
|
||||
|
@ -750,6 +767,13 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if (autoTarget->canDrag()) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
cdebug_log(149,0) << "Perpandical has drag constraints: " << dragConstraints << endl;
|
||||
}
|
||||
|
||||
return (upLayer) ? Flags::AboveLayer : Flags::BelowLayer;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace Anabatic {
|
|||
|
||||
Point sourcePosition;
|
||||
Point targetPosition;
|
||||
Net* net = rp->getNet();
|
||||
const Layer* rpLayer = rp->getLayer();
|
||||
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
|
||||
Flags direction = Session::getDirection ( rpDepth );
|
||||
|
@ -112,6 +113,54 @@ namespace Anabatic {
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Quasi-punctual M1 terminal.
|
||||
if (flags & VSmall) {
|
||||
Box ab = rp->getCell()->getBoundingBox();
|
||||
RoutingLayerGauge* gaugeMetal3 = Session::getLayerGauge( 2 );
|
||||
DbU::Unit metal3axis = gaugeMetal3->getTrackPosition( ab.getYMin()
|
||||
, ab.getYMax()
|
||||
, sourcePosition.getY()
|
||||
, Constant::Nearest );
|
||||
DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0);
|
||||
|
||||
AutoContact* sourceVia12 = AutoContactTerminal::create( sourceGCell
|
||||
, rp
|
||||
, Session::getContactLayer(0)
|
||||
, sourcePosition
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
AutoContact* targetVia12 = AutoContactTerminal::create( targetGCell
|
||||
, rp
|
||||
, Session::getContactLayer(0)
|
||||
, targetPosition
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
AutoContact* sourceVia23 = AutoContactTurn::create( sourceGCell, net, Session::getContactLayer(1) );
|
||||
AutoContact* targetVia23 = AutoContactTurn::create( targetGCell, net, Session::getContactLayer(1) );
|
||||
sourceVia23->setY( metal3axis );
|
||||
targetVia23->setY( metal3axis );
|
||||
sourceVia23->setX( sourcePosition.getX() );
|
||||
targetVia23->setX( targetPosition.getX() );
|
||||
|
||||
AutoSegment* segmentS = AutoSegment::create( sourceVia12, sourceVia23, Flags::Vertical );
|
||||
AutoSegment* segmentT = AutoSegment::create( targetVia12, targetVia23, Flags::Vertical );
|
||||
AutoSegment* segmentM = AutoSegment::create( sourceVia23, targetVia23, Flags::Horizontal );
|
||||
|
||||
sourceVia12->setFlags( CntFixed );
|
||||
sourceVia23->setFlags( CntFixed );
|
||||
targetVia12->setFlags( CntFixed );
|
||||
targetVia23->setFlags( CntFixed );
|
||||
segmentS->setFlags( AutoSegment::SegFixed );
|
||||
segmentT->setFlags( AutoSegment::SegFixed );
|
||||
segmentM->setFlags( AutoSegment::SegFixed );
|
||||
|
||||
cdebug_log(145,0) << "Hard protect: " << rp << endl;
|
||||
cdebug_log(145,0) << "X:" << DbU::getValueString(sourcePosition.getX())
|
||||
<< " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Non-M1 terminal or punctual M1 protections.
|
||||
if ( (rpDepth != 0) or ((sourcePosition == targetPosition) and (gridPosition == 0)) ) {
|
||||
map<Component*,AutoSegment*>::iterator irp = getRpLookup().find( rp );
|
||||
|
|
|
@ -177,8 +177,10 @@ namespace Anabatic {
|
|||
cdebug_log(149,0) << "Align on canonical:" << canonical << endl;
|
||||
|
||||
//canonical->setAxis( canonical->getAxis(), Flags::Realignate );
|
||||
if (canonical->isUnsetAxis()) canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
|
||||
else canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
|
||||
if (canonical->isUnsetAxis() and not canonical->isFixed())
|
||||
canonical->toOptimalAxis( Flags::Realignate|Flags::Propagate );
|
||||
else
|
||||
canonical->setAxis( canonical->getAxis(), Flags::Realignate|Flags::Propagate );
|
||||
aligneds.clear();
|
||||
cdebug_tabw(145,-1);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ namespace Anabatic {
|
|||
, CntIgnoreAnchor = (1 << 11)
|
||||
, CntWeakTerminal = (1 << 12)
|
||||
, CntUserNativeConstraints = (1 << 13)
|
||||
, CntOnVertical = (1 << 14)
|
||||
, CntOnHorizontal = (1 << 15)
|
||||
, CntDrag = (1 << 16)
|
||||
};
|
||||
|
||||
class AutoContact {
|
||||
|
@ -118,12 +121,14 @@ namespace Anabatic {
|
|||
inline bool hasBadTopology () const;
|
||||
bool canDestroy ( Flags flags=Flags::NoFlags ) const;
|
||||
bool canMoveUp ( const AutoSegment* moved ) const;
|
||||
inline bool canDrag () const;
|
||||
// Accessors.
|
||||
inline Contact* base () const;
|
||||
static size_t getAllocateds ();
|
||||
static const Name& getStaticName ();
|
||||
virtual const Name& getName () const;
|
||||
inline size_t getId () const;
|
||||
inline Flags getFlags () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
inline GCell* getGCell () const;
|
||||
virtual AutoSegment* getOpposite ( const AutoSegment* ) const = 0;
|
||||
|
@ -253,7 +258,9 @@ namespace Anabatic {
|
|||
inline bool AutoContact::isHTee () const { return _flags&CntHTee; }
|
||||
inline bool AutoContact::isVTee () const { return _flags&CntVTee; }
|
||||
inline bool AutoContact::hasBadTopology () const { return _flags&CntBadTopology; }
|
||||
inline bool AutoContact::canDrag () const { return _flags&CntDrag; }
|
||||
inline size_t AutoContact::getId () const { return _id; }
|
||||
inline Flags AutoContact::getFlags () const { return _flags; }
|
||||
inline Contact* AutoContact::base () const { return _contact; }
|
||||
inline GCell* AutoContact::getGCell () const { return _gcell; }
|
||||
inline Box AutoContact::getConstraintBox () const { return Box(getCBXMin(),getCBYMin(),getCBXMax(),getCBYMax()); }
|
||||
|
|
|
@ -82,26 +82,27 @@ namespace Anabatic {
|
|||
static const uint64_t SegTargetTop = (1L<<11);
|
||||
static const uint64_t SegTargetBottom = (1L<<12);
|
||||
static const uint64_t SegIsReduced = (1L<<13);
|
||||
static const uint64_t SegLayerChange = (1L<<14);
|
||||
static const uint64_t SegSourceTerminal = (1L<<15); // Replace Terminal.
|
||||
static const uint64_t SegTargetTerminal = (1L<<16); // Replace Terminal.
|
||||
static const uint64_t SegDrag = (1L<<14);
|
||||
static const uint64_t SegLayerChange = (1L<<15);
|
||||
static const uint64_t SegSourceTerminal = (1L<<16); // Replace Terminal.
|
||||
static const uint64_t SegTargetTerminal = (1L<<17); // Replace Terminal.
|
||||
static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal;
|
||||
static const uint64_t SegWeakTerminal1 = (1L<<17); // Replace TopologicalEnd.
|
||||
static const uint64_t SegWeakTerminal2 = (1L<<18); // Replace TopologicalEnd.
|
||||
static const uint64_t SegNotSourceAligned = (1L<<19);
|
||||
static const uint64_t SegNotTargetAligned = (1L<<20);
|
||||
static const uint64_t SegUnbound = (1L<<21);
|
||||
static const uint64_t SegHalfSlackened = (1L<<22);
|
||||
static const uint64_t SegSlackened = (1L<<23);
|
||||
static const uint64_t SegAxisSet = (1L<<24);
|
||||
static const uint64_t SegInvalidated = (1L<<25);
|
||||
static const uint64_t SegInvalidatedSource = (1L<<26);
|
||||
static const uint64_t SegInvalidatedTarget = (1L<<27);
|
||||
static const uint64_t SegInvalidatedLayer = (1L<<28);
|
||||
static const uint64_t SegCreated = (1L<<29);
|
||||
static const uint64_t SegUserDefined = (1L<<30);
|
||||
static const uint64_t SegAnalog = (1L<<31);
|
||||
static const uint64_t SegWide = (1L<<32);
|
||||
static const uint64_t SegWeakTerminal1 = (1L<<18); // Replace TopologicalEnd.
|
||||
static const uint64_t SegWeakTerminal2 = (1L<<19); // Replace TopologicalEnd.
|
||||
static const uint64_t SegNotSourceAligned = (1L<<20);
|
||||
static const uint64_t SegNotTargetAligned = (1L<<21);
|
||||
static const uint64_t SegUnbound = (1L<<22);
|
||||
static const uint64_t SegHalfSlackened = (1L<<23);
|
||||
static const uint64_t SegSlackened = (1L<<24);
|
||||
static const uint64_t SegAxisSet = (1L<<25);
|
||||
static const uint64_t SegInvalidated = (1L<<26);
|
||||
static const uint64_t SegInvalidatedSource = (1L<<27);
|
||||
static const uint64_t SegInvalidatedTarget = (1L<<28);
|
||||
static const uint64_t SegInvalidatedLayer = (1L<<29);
|
||||
static const uint64_t SegCreated = (1L<<30);
|
||||
static const uint64_t SegUserDefined = (1L<<31);
|
||||
static const uint64_t SegAnalog = (1L<<32);
|
||||
static const uint64_t SegWide = (1L<<33);
|
||||
// Masks.
|
||||
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
|
||||
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
|
||||
|
@ -183,6 +184,7 @@ namespace Anabatic {
|
|||
inline bool isWeakTerminal1 () const;
|
||||
inline bool isWeakTerminal2 () const;
|
||||
inline bool isTerminal () const;
|
||||
inline bool isDrag () const;
|
||||
inline bool isNotSourceAligned () const;
|
||||
inline bool isNotTargetAligned () const;
|
||||
inline bool isNotAligned () const;
|
||||
|
@ -480,6 +482,7 @@ namespace Anabatic {
|
|||
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::isDrag () const { return _flags & SegDrag; }
|
||||
inline bool AutoSegment::isNotSourceAligned () const { return _flags & SegNotSourceAligned; }
|
||||
inline bool AutoSegment::isNotTargetAligned () const { return _flags & SegNotTargetAligned; }
|
||||
inline bool AutoSegment::isNotAligned () const { return (_flags & SegNotAligned) == SegNotAligned; }
|
||||
|
|
|
@ -445,7 +445,7 @@ namespace {
|
|||
parser->clearPinSegments();
|
||||
|
||||
cerr << " - " << cellName
|
||||
<< " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << "\n" << endl;
|
||||
<< " " << DbU::getValueString(width) << " " << DbU::getValueString(height) << endl;
|
||||
parser->setCell( NULL );
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -671,10 +671,10 @@ namespace Katana {
|
|||
Interval toFree (_segment->getCanonicalInterval());
|
||||
//Net* ripupNet = NULL;
|
||||
set<TrackElement*> canonicals;
|
||||
DbU::Unit rightAxisHint = 0;
|
||||
DbU::Unit leftAxisHint = 0;
|
||||
bool leftIntrication = false;
|
||||
bool rightIntrication = false;
|
||||
//DbU::Unit rightAxisHint = 0;
|
||||
//DbU::Unit leftAxisHint = 0;
|
||||
//bool leftIntrication = false;
|
||||
//bool rightIntrication = false;
|
||||
bool success = true;
|
||||
|
||||
cdebug_log(159,1) << "Manipulator::_insertInTrack(size_t) - " << toFree << endl;
|
||||
|
@ -785,8 +785,8 @@ namespace Katana {
|
|||
if ( event3->getTracksFree() == 1 ) {
|
||||
cdebug_log(159,0) << "Potential left intrication with other perpandicular." << endl;
|
||||
if ( segment3->getAxis() == segment2->getTargetU() - Session::getExtensionCap(getLayer()) ) {
|
||||
leftIntrication = true;
|
||||
leftAxisHint = segment3->getAxis();
|
||||
//leftIntrication = true;
|
||||
//leftAxisHint = segment3->getAxis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -803,8 +803,8 @@ namespace Katana {
|
|||
if ( event3->getTracksFree() == 1 ) {
|
||||
cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl;
|
||||
if ( segment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap(getLayer()) ) {
|
||||
rightIntrication = true;
|
||||
rightAxisHint = segment3->getAxis();
|
||||
//rightIntrication = true;
|
||||
//rightAxisHint = segment3->getAxis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1422,6 +1422,103 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
bool Manipulator::dragMinimize ()
|
||||
{
|
||||
cdebug_log(159,1) << "Manipulator::dragMinimize() " << _segment << endl;
|
||||
|
||||
if (_segment->isFixed()) { cdebug_tabw(159,-1); return false; }
|
||||
if (not _segment->isDrag()) { cdebug_tabw(159,-1); return false; }
|
||||
|
||||
Interval termConstraints;
|
||||
|
||||
if (_segment->base()->getAutoSource()->canDrag()) {
|
||||
cdebug_log(159,0) << _segment->base()->getAutoSource() << endl;
|
||||
termConstraints = _segment->base()->getAutoSource()->getUConstraints( _segment->getDirection() );
|
||||
cdebug_log(159,0) << "Terminal Constraints (source): " << termConstraints << endl;
|
||||
}
|
||||
if (_segment->base()->getAutoTarget()->canDrag()) {
|
||||
cdebug_log(159,0) << _segment->base()->getAutoTarget() << endl;
|
||||
termConstraints = _segment->base()->getAutoTarget()->getUConstraints( _segment->getDirection() );
|
||||
cdebug_log(159,0) << "Terminal Constraints (target): " << termConstraints << endl;
|
||||
}
|
||||
|
||||
if (_fsm.getCosts().size() == 0) {
|
||||
cerr << Error( "Manipulator::dragMinimize(): The segment cannot be put in any track.\n"
|
||||
" On: %s"
|
||||
, getString(_segment).c_str()
|
||||
) << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_fsm.getCosts().size() > 1)
|
||||
cerr << Error( "Manipulator::dragMinimize(): The segment can be put in more than one track (%d).\n"
|
||||
" On: %s"
|
||||
, _fsm.getCosts().size()
|
||||
, getString(_segment).c_str()
|
||||
) << endl;
|
||||
|
||||
size_t begin = _fsm.getBegin( 0 );
|
||||
size_t end = _fsm.getEnd ( 0 );
|
||||
Track* track = _fsm.getTrack( 0 );
|
||||
DbU::Unit axisHint = 0;
|
||||
|
||||
if (termConstraints.getSize() < _segment->getPPitch()*2) {
|
||||
cdebug_log(159,0) << "Constraints less than two perpandicular pitches, lock." << endl;
|
||||
|
||||
for ( ; begin < end ; ++begin ) {
|
||||
cdebug_log(159,0) << "| Ripup:" << track->getSegment(begin) << endl;
|
||||
_fsm.addAction( track->getSegment(begin), SegmentAction::OtherRipup );
|
||||
}
|
||||
_fsm.addAction( _segment, SegmentAction::SelfLock );
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( ; begin < end ; ++begin ) {
|
||||
TrackElement* conflict = track->getSegment(begin);
|
||||
if (conflict->getCanonicalInterval().intersect( _segment->getCanonicalInterval() )) break;
|
||||
}
|
||||
|
||||
Interval previousFree = track->getPreviousFree( begin, _segment->getNet() );
|
||||
if (previousFree.intersect(termConstraints))
|
||||
axisHint = previousFree.getCenter();
|
||||
else {
|
||||
Interval nextFree = track->getNextFree( end, _segment->getNet() );
|
||||
if (nextFree.intersect(termConstraints)) {
|
||||
axisHint = nextFree.getCenter();
|
||||
} else {
|
||||
cdebug_log(159,0) << "Neither previous free nor next free can be used." << endl;
|
||||
cdebug_log(159,0) << "| previous:" << previousFree << endl;
|
||||
cdebug_log(159,0) << "| next: " << nextFree << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Axis Hint: " << DbU::getValueString(axisHint) << endl;
|
||||
|
||||
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
|
||||
for ( size_t i=0 ; i<perpandiculars.size() ; i++ ) {
|
||||
DataNegociate* data2 = perpandiculars[i]->getDataNegociate();
|
||||
if (not data2) continue;
|
||||
|
||||
cdebug_log(159,0) << " | " << perpandiculars[i] << endl;
|
||||
|
||||
RoutingEvent* event2 = data2->getRoutingEvent();
|
||||
if (not event2) continue;
|
||||
|
||||
_fsm.addAction( perpandiculars[i], SegmentAction::SelfRipupPerpandWithAxisHint, axisHint );
|
||||
}
|
||||
|
||||
_event->setMinimized();
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Manipulator::reprocessPerpandiculars ()
|
||||
{
|
||||
if ( _event->getAxisHistory() == _event->getAxisHint() ) return;
|
||||
|
|
|
@ -41,6 +41,30 @@ namespace {
|
|||
using Anabatic::perpandicularTo;
|
||||
using Anabatic::AutoSegment;
|
||||
using Anabatic::AutoContactTerminal;
|
||||
using Anabatic::AutoSegments_OnContact;
|
||||
using Anabatic::AutoSegments;
|
||||
|
||||
|
||||
class SortAcByXY {
|
||||
public:
|
||||
inline bool operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 );
|
||||
};
|
||||
|
||||
|
||||
inline bool SortAcByXY::operator() ( AutoContactTerminal* contact1, AutoContactTerminal* contact2 )
|
||||
{
|
||||
DbU::Unit x1 = contact1->getX();
|
||||
DbU::Unit x2 = contact2->getX();
|
||||
|
||||
if (x1 == x2) {
|
||||
DbU::Unit y1 = contact1->getY();
|
||||
DbU::Unit y2 = contact2->getY();
|
||||
|
||||
if (y1 == y2) return false;
|
||||
return (y1 < y2);
|
||||
}
|
||||
return (x1 < x2);
|
||||
}
|
||||
|
||||
|
||||
void getPerpandiculars ( TrackElement* segment
|
||||
|
@ -323,6 +347,85 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
void metal2protect ( AutoContactTerminal* contact )
|
||||
{
|
||||
const Layer* metal2 = Session::getRoutingLayer(1);
|
||||
RoutingPlane* metal3plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( 2 );
|
||||
DbU::Unit metal3axis = metal3plane->getTrackByPosition( contact->getY() )->getAxis();
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( contact->getAnchor() );
|
||||
DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0);
|
||||
Point position ( contact->getX(), metal3axis );
|
||||
|
||||
AutoContact* sourceVia12 = AutoContactTerminal::create( contact->getGCell()
|
||||
, rp
|
||||
, metal2
|
||||
, position
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
AutoContact* targetVia12 = AutoContactTerminal::create( contact->getGCell()
|
||||
, rp
|
||||
, metal2
|
||||
, position
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
|
||||
AutoSegment* segment = AutoSegment::create( sourceVia12, targetVia12, Flags::Vertical );
|
||||
|
||||
sourceVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
|
||||
targetVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
|
||||
segment->setFlags( AutoSegment::SegFixed );
|
||||
|
||||
Session::getNegociateWindow()->createTrackSegment( segment, Flags::LoadingStage );
|
||||
|
||||
cdebug_log(145,0) << "Hard protect: " << contact << endl;
|
||||
cdebug_log(145,0) << "X:" << DbU::getValueString(position.getX())
|
||||
<< " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl;
|
||||
}
|
||||
|
||||
|
||||
void protectAlignedAccesses ( GCell* gcell )
|
||||
{
|
||||
DbU::Unit pitch3 = Session::getPitch( 2 );
|
||||
|
||||
multiset<AutoContactTerminal*,SortAcByXY> acTerminals;
|
||||
for ( AutoContact* contact : gcell->getContacts() ) {
|
||||
if (contact->isTerminal() and (Session::getViaDepth(contact->getLayer()) == 0) )
|
||||
acTerminals.insert( dynamic_cast<AutoContactTerminal*>(contact) );
|
||||
}
|
||||
|
||||
AutoContactTerminal* south = NULL;
|
||||
for ( AutoContactTerminal* north : acTerminals ) {
|
||||
if (south) {
|
||||
if (south->canDrag() and north->canDrag() and (south->getX() == north->getX())) {
|
||||
//Interval constraints ( north->getCBYMax() - pitch3, gcell->getYMin() );
|
||||
Interval constraints ( north->getCBYMin() - pitch3, gcell->getYMin() );
|
||||
AutoSegment* terminal = south->getSegment();
|
||||
AutoContact* opposite = terminal->getOppositeAnchor( south );
|
||||
|
||||
for ( AutoSegment* segment : AutoSegments_OnContact(terminal,opposite->base()) ) {
|
||||
segment->mergeUserConstraints( constraints );
|
||||
cerr << "Apply " << constraints << " to " << segment << endl;
|
||||
}
|
||||
|
||||
//constraints = Interval( south->getCBYMin() + pitch3, gcell->getYMax() );
|
||||
constraints = Interval( south->getCBYMax() + pitch3, gcell->getYMax() );
|
||||
terminal = north->getSegment();
|
||||
opposite = terminal->getOppositeAnchor( north );
|
||||
|
||||
for ( AutoSegment* segment : AutoSegments_OnContact(terminal,opposite->base()) ) {
|
||||
segment->mergeUserConstraints( constraints );
|
||||
cerr << "Apply " << constraints << " to " << segment << endl;
|
||||
}
|
||||
}
|
||||
|
||||
//if (south->getConstraintBox().getHeight() < pitch3*2) metal2protect( south );
|
||||
//if (north->getConstraintBox().getHeight() < pitch3*2) metal2protect( north );
|
||||
}
|
||||
south = north;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of local namespace.
|
||||
|
||||
|
||||
|
@ -337,6 +440,8 @@ namespace Katana {
|
|||
|
||||
void KatanaEngine::preProcess ()
|
||||
{
|
||||
//DebugSession::open( 145, 150 );
|
||||
|
||||
for ( size_t i=0 ; i<_routingPlanes.size() ; ++i ) {
|
||||
RoutingPlane* plane = _routingPlanes[i];
|
||||
|
||||
|
@ -346,6 +451,11 @@ namespace Katana {
|
|||
track = track->getNextTrack();
|
||||
}
|
||||
}
|
||||
|
||||
for ( GCell* gcell : getGCells() ) protectAlignedAccesses( gcell );
|
||||
|
||||
//DebugSession::close();
|
||||
|
||||
Session::revalidate ();
|
||||
}
|
||||
|
||||
|
|
|
@ -365,7 +365,9 @@ namespace Katana {
|
|||
|
||||
DebugSession::open( _segment->getNet(), 156, 160 );
|
||||
|
||||
if (_type & Perpandicular) {
|
||||
if (_type & Lock) {
|
||||
cdebug_log(159,0) << "* Lock // " << _segment << endl;
|
||||
} else if (_type & Perpandicular) {
|
||||
cdebug_log(159,0) << "* Riping Pp " << _segment << endl;
|
||||
} else {
|
||||
cdebug_log(159,0) << "* Riping // " << _segment << endl;
|
||||
|
@ -393,6 +395,8 @@ namespace Katana {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_type&Lock) Session::addLockEvent( _segment );
|
||||
|
||||
if ( (_type & AxisHint) /*and not _segment->isSlackenDogleg()*/ ) {
|
||||
cdebug_log(159,0) << "Setting Axis Hint: @" << DbU::getValueString(_axisHint) << endl;
|
||||
event->setAxisHint( _axisHint );
|
||||
|
@ -1177,6 +1181,7 @@ namespace Katana {
|
|||
uint32_t nextState = data->getState();
|
||||
Manipulator manipulator ( segment, *this );
|
||||
|
||||
|
||||
switch (data->getState()) {
|
||||
case DataNegociate::RipupPerpandiculars:
|
||||
nextState = DataNegociate::Minimize;
|
||||
|
@ -1189,7 +1194,10 @@ namespace Katana {
|
|||
break;
|
||||
}
|
||||
nextState = DataNegociate::Dogleg;
|
||||
success = manipulator.minimize();
|
||||
// if (segment->isDrag())
|
||||
// success = manipulator.dragMinimize();
|
||||
// else
|
||||
success = manipulator.minimize();
|
||||
if (success) break;
|
||||
case DataNegociate::Dogleg:
|
||||
nextState = DataNegociate::Slacken;
|
||||
|
@ -1222,6 +1230,7 @@ namespace Katana {
|
|||
}
|
||||
}
|
||||
case DataNegociate::Unimplemented:
|
||||
if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl;
|
||||
nextState = DataNegociate::Unimplemented;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -17,21 +17,68 @@
|
|||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Point.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "anabatic/AutoContactTerminal.h"
|
||||
#include "katana/Session.h"
|
||||
#include "katana/Track.h"
|
||||
#include "katana/TrackElement.h"
|
||||
#include "katana/KatanaEngine.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/NegociateWindow.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std;
|
||||
using namespace Hurricane;
|
||||
using namespace CRL;
|
||||
using namespace Katana;
|
||||
using Anabatic::perpandicularTo;
|
||||
using Anabatic::AutoSegment;
|
||||
using Anabatic::AutoContactTerminal;
|
||||
using Anabatic::AutoSegments_OnContact;
|
||||
using Anabatic::AutoSegments;
|
||||
|
||||
|
||||
const char* reopenSession = "Katana::Session::_open(): Session already open for %s (internal error).";
|
||||
|
||||
|
||||
void metal2protect ( AutoContactTerminal* contact )
|
||||
{
|
||||
const Layer* metal2 = Session::getRoutingLayer(1);
|
||||
RoutingPlane* metal3plane = Session::getKatanaEngine()->getRoutingPlaneByIndex( 2 );
|
||||
DbU::Unit metal3axis = metal3plane->getTrackByPosition( contact->getY() )->getAxis();
|
||||
RoutingPad* rp = dynamic_cast<RoutingPad*>( contact->getAnchor() );
|
||||
DbU::Unit viaSideProtect = Session::getViaWidth((size_t)0);
|
||||
Point position ( contact->getX(), metal3axis );
|
||||
|
||||
AutoContact* sourceVia12 = AutoContactTerminal::create( contact->getGCell()
|
||||
, rp
|
||||
, metal2
|
||||
, position
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
AutoContact* targetVia12 = AutoContactTerminal::create( contact->getGCell()
|
||||
, rp
|
||||
, metal2
|
||||
, position
|
||||
, viaSideProtect, viaSideProtect
|
||||
);
|
||||
|
||||
AutoSegment* segment = AutoSegment::create( sourceVia12, targetVia12, Flags::Vertical );
|
||||
|
||||
sourceVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
|
||||
targetVia12->setFlags( Anabatic::CntFixed|Anabatic::CntIgnoreAnchor );
|
||||
segment->setFlags( AutoSegment::SegFixed );
|
||||
|
||||
Session::getNegociateWindow()->createTrackSegment( segment, Flags::NoFlags );
|
||||
|
||||
cdebug_log(145,0) << "Hard protect: " << contact << endl;
|
||||
cdebug_log(145,0) << "X:" << DbU::getValueString(position.getX())
|
||||
<< " Metal3 Track Y:" << DbU::getValueString(metal3axis) << endl;
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
|
@ -149,10 +196,23 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void Session::_doLockEvents ()
|
||||
{
|
||||
for ( size_t i=0 ; i<_lockEvents.size() ; ++i ) {
|
||||
AutoContactTerminal* source = dynamic_cast<AutoContactTerminal*>( _lockEvents[i]._segment->base()->getAutoSource() );
|
||||
AutoContactTerminal* target = dynamic_cast<AutoContactTerminal*>( _lockEvents[i]._segment->base()->getAutoTarget() );
|
||||
if (source and source->canDrag()) metal2protect( source );
|
||||
if (target and target->canDrag()) metal2protect( target );
|
||||
}
|
||||
_lockEvents.clear();
|
||||
}
|
||||
|
||||
|
||||
size_t Session::_revalidate ()
|
||||
{
|
||||
cdebug_log(159,1) << "Katana::Session::_revalidate()" << endl;
|
||||
|
||||
_doLockEvents();
|
||||
_doRemovalEvents();
|
||||
|
||||
for ( const Event& event : _insertEvents ) {
|
||||
|
@ -302,6 +362,19 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void Session::_addLockEvent ( TrackElement* segment )
|
||||
{
|
||||
if (not segment->isTerminal()) {
|
||||
cerr << Bug( " Katana::Session::addLockEvent() : %s is not connected to a terminal."
|
||||
, getString(segment).c_str() ) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Lock: @" << DbU::getValueString(segment->getAxis()) << " " << segment << endl;
|
||||
_lockEvents.push_back( Event(segment,NULL) );
|
||||
}
|
||||
|
||||
|
||||
void Session::_addMoveEvent ( TrackElement* segment, Track* track )
|
||||
{
|
||||
if (not segment->getTrack()) {
|
||||
|
|
|
@ -589,6 +589,42 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
Interval Track::getNextFree ( size_t index, Net* net )
|
||||
{
|
||||
if (_segments.empty()) return Interval( _min, _max );
|
||||
|
||||
if (index >= _segments.size()) {
|
||||
size_t last = _segments.size()-1;
|
||||
return Interval( getOccupiedInterval(last).getVMax(), _max );
|
||||
}
|
||||
|
||||
Interval occupied = getOccupiedInterval( index );
|
||||
return getFreeInterval( occupied.getVMax()+1, net );
|
||||
}
|
||||
|
||||
|
||||
Interval Track::getPreviousFree ( size_t index, Net* net )
|
||||
{
|
||||
cdebug_log(155,1) << "Track::getPreviousFree() index:" << index << " " << net << endl;
|
||||
|
||||
if (_segments.empty()) { cdebug_tabw(155,-1); return Interval( _min, _max ); }
|
||||
|
||||
if (index == 0) {
|
||||
size_t first = 0;
|
||||
Interval free = Interval( _min, getOccupiedInterval(first).getVMin() );
|
||||
cdebug_tabw(155,-1);
|
||||
return free;
|
||||
}
|
||||
|
||||
|
||||
Interval occupied = getOccupiedInterval( index );
|
||||
cdebug_log(155,0) << "Previous occupied:" << occupied << endl;
|
||||
Interval free = getFreeInterval( occupied.getVMin()-1, net );
|
||||
cdebug_tabw(155,-1);
|
||||
return free;
|
||||
}
|
||||
|
||||
|
||||
Interval Track::getOccupiedInterval ( size_t& begin ) const
|
||||
{
|
||||
if (begin == npos) return Interval();
|
||||
|
|
|
@ -137,6 +137,7 @@ namespace Katana {
|
|||
bool TrackElement::isGlobal () const { return not isLocal(); }
|
||||
bool TrackElement::isBipoint () const { return false; }
|
||||
bool TrackElement::isTerminal () const { return false; }
|
||||
bool TrackElement::isDrag () const { return false; }
|
||||
bool TrackElement::isStrongTerminal ( Flags ) const { return false; }
|
||||
bool TrackElement::isStrap () const { return false; }
|
||||
bool TrackElement::isSlackened () const { return false; }
|
||||
|
|
|
@ -160,6 +160,7 @@ namespace Katana {
|
|||
bool TrackSegment::isGlobal () const { return _base->isWeakGlobal() or _base->isGlobal(); }
|
||||
bool TrackSegment::isBipoint () const { return _base->isBipoint(); }
|
||||
bool TrackSegment::isTerminal () const { return _base->isTerminal(); }
|
||||
bool TrackSegment::isDrag () const { return _base->isDrag(); }
|
||||
bool TrackSegment::isStrongTerminal ( Flags flags ) const { return _base->isStrongTerminal(flags); }
|
||||
bool TrackSegment::isStrap () const { return _base->isStrap(); }
|
||||
bool TrackSegment::isSlackened () const { return _base->isSlackened(); }
|
||||
|
|
|
@ -67,6 +67,7 @@ namespace Katana {
|
|||
void reprocessPerpandiculars ();
|
||||
bool ripple ();
|
||||
bool minimize ();
|
||||
bool dragMinimize ();
|
||||
bool slacken ( Flags flags=Flags::NoFlags );
|
||||
bool pivotUp ();
|
||||
bool pivotDown ();
|
||||
|
|
|
@ -43,13 +43,15 @@ namespace Katana {
|
|||
, ToRipupLimit = (1<< 7)
|
||||
, MoveToAxis = (1<< 8)
|
||||
, AxisHint = (1<< 9)
|
||||
, PackingMode = (1<<10)
|
||||
, ToState = (1<<11)
|
||||
, EventLevel1 = (1<<12)
|
||||
, EventLevel2 = (1<<13)
|
||||
, EventLevel3 = (1<<14)
|
||||
, EventLevel4 = (1<<15)
|
||||
, EventLevel5 = (1<<16)
|
||||
, Lock = (1<<10)
|
||||
, PackingMode = (1<<11)
|
||||
, ToState = (1<<12)
|
||||
, EventLevel1 = (1<<13)
|
||||
, EventLevel2 = (1<<14)
|
||||
, EventLevel3 = (1<<15)
|
||||
, EventLevel4 = (1<<16)
|
||||
, EventLevel5 = (1<<17)
|
||||
, SelfLock = Self |Lock
|
||||
, SelfInsert = Self |Insert
|
||||
, SelfRipup = Self |Ripup
|
||||
, SelfRipupPerpand = Self |Ripup|Perpandicular
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace Katana {
|
|||
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* );
|
||||
|
@ -89,6 +90,7 @@ namespace Katana {
|
|||
Net* _getBlockageNet ();
|
||||
uint32_t _getRipupCost ();
|
||||
Anabatic::GCell* _getGCellUnder ( DbU::Unit, DbU::Unit );
|
||||
void _doLockEvents ();
|
||||
void _doRemovalEvents ();
|
||||
virtual size_t _revalidate ();
|
||||
bool _isEmpty () const;
|
||||
|
@ -98,6 +100,7 @@ namespace Katana {
|
|||
void _addRemoveEvent ( TrackElement* );
|
||||
void _addMoveEvent ( TrackElement* , Track* );
|
||||
void _addSortEvent ( Track*, bool forced );
|
||||
void _addLockEvent ( TrackElement* );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual string _getTypeName () const;
|
||||
protected:
|
||||
|
@ -115,6 +118,7 @@ namespace Katana {
|
|||
// Attributes.
|
||||
vector<Event> _insertEvents;
|
||||
vector<Event> _removeEvents;
|
||||
vector<Event> _lockEvents;
|
||||
set<Track*> _sortEvents;
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
|
@ -172,6 +176,9 @@ namespace Katana {
|
|||
inline void Session::addMoveEvent ( TrackElement* segment, Track* track )
|
||||
{ get("addMoveEvent()")->_addMoveEvent(segment,track); }
|
||||
|
||||
inline void Session::addLockEvent ( TrackElement* segment )
|
||||
{ get("addLockEvent()")->_addLockEvent(segment); }
|
||||
|
||||
inline void Session::addSortEvent ( Track* track, bool forced )
|
||||
{ get("addSortEvent()")->_addSortEvent(track,forced); }
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace Katana {
|
|||
DbU::Unit getMinimalPosition ( size_t index, uint32_t state ) const;
|
||||
DbU::Unit getMaximalPosition ( size_t index, uint32_t state ) const;
|
||||
Interval getFreeInterval ( DbU::Unit position, Net* net=NULL ) const;
|
||||
Interval getNextFree ( size_t index, Net* net );
|
||||
Interval getPreviousFree ( size_t index, Net* net );
|
||||
Interval getOccupiedInterval ( size_t& begin ) const;
|
||||
Interval expandFreeInterval ( size_t& begin, size_t& end, uint32_t state, Net* ) const;
|
||||
void getBeginIndex ( DbU::Unit position, size_t& begin, uint32_t& state ) const;
|
||||
|
|
|
@ -106,6 +106,7 @@ namespace Katana {
|
|||
virtual bool isGlobal () const;
|
||||
virtual bool isBipoint () const;
|
||||
virtual bool isTerminal () const;
|
||||
virtual bool isDrag () const;
|
||||
virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
|
||||
virtual bool isStrap () const;
|
||||
virtual bool isSlackened () const;
|
||||
|
|
|
@ -69,6 +69,7 @@ namespace Katana {
|
|||
virtual bool isGlobal () const;
|
||||
virtual bool isBipoint () const;
|
||||
virtual bool isTerminal () const;
|
||||
virtual bool isDrag () const;
|
||||
virtual bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
|
||||
virtual bool isStrap () const;
|
||||
virtual bool isSlackened () const;
|
||||
|
|
Loading…
Reference in New Issue