Basic support for FreePDK 45 completed.
* New: In Commons, inspector support for std::pair<T,U>. * New: In Hurricane::Layer, ContactLayer & ViaLayer, support for non square VIAs. The hole (cut) remains square, but the various metal extensions can now be different in X and Y. The ::getEnclosure() method now takes a flag EnclosureH / EnclosureV. * New: In Hurricane::DbU, inspector support for: std::pair<DbU::Unit,DbU::Unit> std::array<DbU::Unit,3> Must be defined here as DbU do not exists yet in Commons.h * Bug: In Hurricane::Interval::getSize(), when the interval is "full span", do not return the difference between min and max, but directly DbU::Max. (the previous result was -1 !) * New: In CRL Core Python/Technology.py, support for non square VIAs in the configuration files. Applied to FreePDK 45. * New: In CRL::RoutingGauge, added a "symbolic" flag to tell if a gauge is for symbolic layout or not. Exported to Python. * New: In Anabatic::AutoHorizontal::updatePosition(), differentiated computation for soure or target taking account of the VIA extension in the right segment metal (due to non-square VIAs). * Change: In Anabatic::AutoHorizontal::_makeDogleg(), the dogleg is UP for HV gauges and DOWN for VH. * New: In Anabatic::AutoSegment::_initialize(), create a cache of the various extension length for each layer (viaToTop, viaToBottom, viaToSame). New implementation of getExtensionCap() using the previous cached extension table. See updatePositions(). New static functions to access the extension cache in the header: getViaTotopCap() ... * Change: In Anabatic::AutoSegment, in various update methods, updateOrient() must always be called *before* updatePositions() as extensions are dependant on source/target. * New: In Anabatic::AutoSegment::getEndAxes() compute the position of the first source and last target position (center/axes) on an *aligned* set of segments. * New: In Anabatic::AutoSegment, add a new state flag SegAxisFixed to signal segments that can be put on only one track. Specific case to VH gauge for a M1 vertical terminal with a M2 vertical segment. The M2 is effectively bound to the M1 axis position. * Bug: In Anabatic::NetBuilderVH::_do_xG_xM1_xM3(), in case of E/W global and only one RoutingPad the connexion to the RoutingPad was duplicated. It was valid, but totally stupid. * Bug: In Anabatic::Session::_canonize(), for an aligned segment set, intersect the user constraints from all segments instead of only considering the canonical one. Issue a warning about too tight constraints only for symbolic gauges. It may be correct for the real ones. * New: In Katata::DataNegociate::update(), more accurate computation of the perpandicular free interval. Use segment extension cap calculation. Create a special case for fixed axis segments allowing them to find alternative free interval, try under source and under target as they are likely to be draggable segments. * Change: In Katana::Manipulator::relax(), use the extension cap value to compute the axis of the perpandicular segemnts. * Change: In Katana::Manipulator::moveUp(), now move up the whole set of aligned segments instead of just the canonical one. * Change: In Katana::NegociateWindow::loadRoutingPads(), more accurate TrackMarkers insertions for fixed terminals. * New: In Katana::RoutingEvent::Key::Compare::operator(), segments with fixed axis are processed prior to any others. * New: In Katana::RoutingEventLoop, store segment pointers instead of ids to generate more accurate error messages. * Change: In Katana::RoutingPlane::create(), perform local track assignment only for HV gauges. * Change: In Katana::SegmentFsm::_slackenLocal(), add a "dragMinimize" step in the automaton. Mutliple states transitions can occurs in a row if an action fails. * New: In Katana::Session::_toIntervalAxis(), normalize interval bounds so they are on track positions (by shrinking the interval). * Bug: In Katana::TrackMarker CTOR, the weigh computation was wrong.
This commit is contained in:
parent
7bcf47212b
commit
592c098ab2
|
@ -18,6 +18,7 @@
|
|||
#include <iostream>
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/RegularLayer.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
|
@ -29,20 +30,108 @@
|
|||
#include "crlcore/RoutingGauge.h"
|
||||
#include "crlcore/Measures.h"
|
||||
#include "anabatic/GCell.h"
|
||||
#include "anabatic/AutoContactTerminal.h"
|
||||
#include "anabatic/NetBuilderM2.h"
|
||||
#include "anabatic/NetBuilderHV.h"
|
||||
#include "anabatic/NetBuilderVH.h"
|
||||
#include "anabatic/AnabaticEngine.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace Hurricane;
|
||||
using namespace Anabatic;
|
||||
|
||||
|
||||
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 shear ( AutoSegment* segment )
|
||||
{
|
||||
AutoContact* source = segment->getAutoSource();
|
||||
AutoContact* target = segment->getAutoTarget();
|
||||
bool useSource = true;
|
||||
|
||||
if (segment->isHorizontal()) {
|
||||
if (not source->isTurn() and target->isTurn()) useSource = false;
|
||||
} else {
|
||||
if (not source->isTurn() and target->isTurn()) useSource = false;
|
||||
}
|
||||
|
||||
segment->makeDogleg( (useSource ? source->getGCell() : target->getGCell()) );
|
||||
Session::getDoglegs()[ Session::getDoglegs().size()-2 ]->unsetFlags( AutoSegment::SegAxisSet );
|
||||
|
||||
#if BAD_RESULTS
|
||||
AutoContact* source = segment->getAutoSource();
|
||||
AutoContact* target = segment->getAutoTarget();
|
||||
AutoSegment* perpandicular = NULL;
|
||||
bool useSource = true;
|
||||
|
||||
if (segment->isHorizontal()) {
|
||||
if (source->isTurn()) perpandicular = source->getPerpandicular( segment );
|
||||
else {
|
||||
if (target->isTurn()) { perpandicular = target->getPerpandicular( segment ); useSource = false; }
|
||||
else {
|
||||
if (source->isHTee()) perpandicular = source->getPerpandicular( segment );
|
||||
else {
|
||||
if (target->isHTee()) { perpandicular = target->getPerpandicular( segment ); useSource = false; }
|
||||
else
|
||||
perpandicular = segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (source->isTurn()) perpandicular = source->getPerpandicular( segment );
|
||||
else {
|
||||
if (target->isTurn()) { perpandicular = target->getPerpandicular( segment ); useSource = false; }
|
||||
else {
|
||||
if (source->isVTee()) perpandicular = source->getPerpandicular( segment );
|
||||
else {
|
||||
if (target->isVTee()) { perpandicular = target->getPerpandicular( segment ); useSource = false; }
|
||||
else
|
||||
perpandicular = segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
perpandicular->makeDogleg( (useSource ? source->getGCell() : target->getGCell()) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace Anabatic {
|
||||
|
||||
using std::cerr;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::multiset;
|
||||
using std::ostringstream;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::RegularLayer;
|
||||
using Hurricane::Component;
|
||||
|
@ -416,6 +505,7 @@ namespace Anabatic {
|
|||
for ( GCell* gcell : _gcells ) _updateLookup( gcell );
|
||||
}
|
||||
|
||||
|
||||
size_t AnabaticEngine::getNetsFromEdge ( const Edge* edge, NetSet& nets )
|
||||
{
|
||||
size_t count = 0;
|
||||
|
@ -719,11 +809,136 @@ namespace Anabatic {
|
|||
throw Error( badMethod, "Anabatic::loadGlobalRouting()", method, getString(_cell).c_str() );
|
||||
}
|
||||
cleanupGlobal();
|
||||
relaxOverConstraineds();
|
||||
|
||||
_state = EngineActive;
|
||||
}
|
||||
|
||||
|
||||
void AnabaticEngine::relaxOverConstraineds ()
|
||||
{
|
||||
openSession();
|
||||
|
||||
DbU::Unit pitch3 = Session::getPitch( 2 );
|
||||
AutoSegment::IdSet constraineds;
|
||||
AutoSegment::IdSet processeds;
|
||||
|
||||
for ( GCell* gcell : _gcells ) {
|
||||
//cerr << "@ " << gcell << endl;
|
||||
|
||||
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 ) {
|
||||
//cerr << "@ " << north << endl;
|
||||
if (south) {
|
||||
if ( south->canDrag()
|
||||
and north->canDrag()
|
||||
and (south->getNet() != north->getNet())
|
||||
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 );
|
||||
constraineds.insert( segment );
|
||||
//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 );
|
||||
constraineds.insert( segment );
|
||||
//cerr << "Apply " << constraints << " to " << segment << endl;
|
||||
}
|
||||
}
|
||||
|
||||
//if (south->getConstraintBox().getHeight() < pitch3*2) metal2protect( south );
|
||||
//if (north->getConstraintBox().getHeight() < pitch3*2) metal2protect( north );
|
||||
}
|
||||
south = north;
|
||||
}
|
||||
}
|
||||
|
||||
Session::revalidate();
|
||||
|
||||
for ( AutoSegment* constrained : constraineds ) {
|
||||
if (processeds.find(constrained) != processeds.end()) continue;
|
||||
processeds.insert( constrained );
|
||||
|
||||
Interval userConstraints ( false );
|
||||
vector<AutoSegment*> aligneds;
|
||||
|
||||
aligneds.push_back( constrained );
|
||||
|
||||
for ( AutoSegment* aligned : constrained->getAligneds() ) {
|
||||
aligneds.push_back( aligned );
|
||||
processeds.insert( aligned );
|
||||
}
|
||||
|
||||
sort( aligneds.begin(), aligneds.end(), AutoSegment::CompareBySourceU() );
|
||||
|
||||
AutoSegment* previous = NULL;
|
||||
for ( AutoSegment* aligned : aligneds ) {
|
||||
Interval constraints = userConstraints.getIntersection( aligned->getUserConstraints() );
|
||||
cerr << "aligned: " << aligned << " " << aligned->getUserConstraints() << endl;
|
||||
|
||||
if (constraints.getSize() < Session::getPitch(1)) {
|
||||
if (not previous) {
|
||||
cerr << Warning( "protectAlignedAccesses(): Shearing constraints between S/T on\n"
|
||||
" %s\n"
|
||||
" S:%s\n"
|
||||
" T:%s\n"
|
||||
" Combined user constraints are too tight [%s : %s]."
|
||||
, getString(aligned ).c_str()
|
||||
, getString(aligned->getAutoSource()->getConstraintBox()).c_str()
|
||||
, getString(aligned->getAutoTarget()->getConstraintBox()).c_str()
|
||||
, DbU::getValueString(constraints.getVMin()).c_str()
|
||||
, DbU::getValueString(constraints.getVMax()).c_str()
|
||||
) << endl;
|
||||
} else {
|
||||
cerr << Warning( "protectAlignedAccesses(): Shearing constraints between\n"
|
||||
" %s\n"
|
||||
" %s\n"
|
||||
" Combined user constraints are too tight [%s : %s]."
|
||||
, getString(previous).c_str()
|
||||
, getString(aligned ).c_str()
|
||||
, DbU::getValueString(constraints.getVMin()).c_str()
|
||||
, DbU::getValueString(constraints.getVMax()).c_str()
|
||||
) << endl;
|
||||
}
|
||||
//if (previous) {
|
||||
// if (previous->getAutoTarget() == aligned->getAutoSource()) {
|
||||
// cerr << "Found a shared contact: " << aligned->getAutoSource() << endl;
|
||||
shear( aligned );
|
||||
// }
|
||||
//}
|
||||
|
||||
userConstraints = aligned->getUserConstraints();
|
||||
} else {
|
||||
userConstraints = constraints;
|
||||
}
|
||||
|
||||
previous = aligned;
|
||||
}
|
||||
|
||||
cerr << "Final user constraints:" << userConstraints << endl;
|
||||
}
|
||||
|
||||
Session::close();
|
||||
}
|
||||
|
||||
|
||||
void AnabaticEngine::_loadGrByNet ()
|
||||
{
|
||||
cmess1 << " o Building detailed routing from global. " << endl;
|
||||
|
|
|
@ -91,8 +91,11 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* ) const
|
||||
{ return NULL; }
|
||||
AutoSegment* AutoContactHTee::getPerpandicular ( const AutoSegment* from ) const
|
||||
{
|
||||
if ( (from == _horizontal1) or (from == _horizontal2) ) return _vertical1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
AutoSegment* AutoContactHTee::getSegment ( unsigned int index ) const
|
||||
|
|
|
@ -172,7 +172,34 @@ namespace Anabatic {
|
|||
if (component == NULL) {
|
||||
cerr << Error( "%s is not anchored.", getString(this).c_str() ) << endl;
|
||||
cdebug_tabw(145,-1);
|
||||
return _gcell->getBoundingBox ();
|
||||
return _gcell->getBoundingBox();
|
||||
}
|
||||
|
||||
RoutingLayerGauge* lg = Session::getLayerGauge( Session::getLayerDepth(component->getLayer()) );
|
||||
DbU::Unit xborder = 0;
|
||||
DbU::Unit yborder = 0;
|
||||
const Layer* viaLayer = Session::getContactLayer( lg->getDepth() );
|
||||
|
||||
if (viaLayer) {
|
||||
if (lg->isHorizontal() and (lg->getDepth() != 0)) {
|
||||
xborder = Session::getViaWidth( lg->getDepth() )/2
|
||||
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
|
||||
} else {
|
||||
yborder = Session::getViaWidth( lg->getDepth() )/2
|
||||
+ viaLayer->getBottomEnclosure( Layer::EnclosureV );
|
||||
xborder = Session::getViaWidth( lg->getDepth() )/2
|
||||
+ viaLayer->getBottomEnclosure( Layer::EnclosureH );
|
||||
|
||||
if (Session::getRoutingGauge()->isSymbolic()) {
|
||||
// SxLib bug: METAL1 terminal segments are 0.5 lambdas too shorts on
|
||||
// their extremities. Should modificate all the standard cells layout...
|
||||
// HARDCODED.
|
||||
if (Session::getRoutingGauge()->getName() == "msxlib")
|
||||
yborder -= DbU::fromLambda( 1.0 );
|
||||
else
|
||||
yborder -= DbU::fromLambda( 0.5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DbU::Unit xMin;
|
||||
|
@ -211,6 +238,17 @@ namespace Anabatic {
|
|||
if (vertical) { bb = vertical ->getBoundingBox(); const_cast<AutoContactTerminal*>(this)->setFlags( CntOnVertical ); }
|
||||
|
||||
transformation.applyOn( bb );
|
||||
cdebug_log(145,0) << "Shrink border x:" << DbU::getValueString(xborder)
|
||||
<< " y:" << DbU::getValueString(yborder)
|
||||
<< endl;
|
||||
|
||||
// HARDCODED.
|
||||
if ( (Session::getRoutingGauge()->getName() == "sxlib")
|
||||
and (bb.getWidth() == DbU::fromLambda(1.0)) ) {
|
||||
bb.inflate( DbU::fromLambda(0.5), 0 );
|
||||
}
|
||||
|
||||
bb.inflate( -xborder, -yborder );
|
||||
xMin = bb.getXMin();
|
||||
yMin = bb.getYMin();
|
||||
xMax = bb.getXMax();
|
||||
|
@ -298,6 +336,7 @@ namespace Anabatic {
|
|||
void AutoContactTerminal::cacheDetach ( AutoSegment* segment )
|
||||
{
|
||||
if (_segment == segment) {
|
||||
_segment->unsetFlags( AutoSegment::SegAxisSet );
|
||||
_segment = NULL;
|
||||
setFlags( CntInvalidatedCache );
|
||||
unsetFlags( CntDrag );
|
||||
|
@ -325,7 +364,7 @@ namespace Anabatic {
|
|||
|
||||
if ( (dynamic_cast<AutoHorizontal*>(_segment) and (getFlags() & CntOnHorizontal))
|
||||
or (dynamic_cast<AutoVertical*> (_segment) and (getFlags() & CntOnVertical )) ) {
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegAxisSet );
|
||||
setFlags( CntDrag );
|
||||
|
||||
cdebug_log(145,0) << "Drag Contact/Segment set" << endl;
|
||||
|
@ -364,13 +403,13 @@ namespace Anabatic {
|
|||
_segment = Session::lookup( horizontals[0] );
|
||||
if (getFlags() & CntOnHorizontal) {
|
||||
setFlags( CntDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
|
||||
}
|
||||
} else {
|
||||
_segment = Session::lookup( verticals[0] );
|
||||
if (getFlags() & CntOnVertical) {
|
||||
setFlags( CntDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag );
|
||||
_segment->setFlags( AutoSegment::SegDrag|AutoSegment::SegFixedAxis );
|
||||
}
|
||||
}
|
||||
if (_segment == NULL) {
|
||||
|
|
|
@ -91,8 +91,11 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* ) const
|
||||
{ return NULL; }
|
||||
AutoSegment* AutoContactVTee::getPerpandicular ( const AutoSegment* from ) const
|
||||
{
|
||||
if ( (from == _vertical1) or (from == _vertical2) ) return _horizontal1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
AutoSegment* AutoContactVTee::getSegment ( unsigned int index ) const
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/ViaLayer.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "anabatic/Configuration.h"
|
||||
|
@ -35,6 +36,7 @@ namespace Anabatic {
|
|||
using Hurricane::Error;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::ViaLayer;
|
||||
using Hurricane::RoutingPad;
|
||||
|
||||
|
||||
|
@ -330,7 +332,7 @@ namespace Anabatic {
|
|||
|
||||
const vector<AutoSegment*>& doglegs = Session::getDoglegs();
|
||||
if (sourceSlackened and (doglegs.size() >= 2)) {
|
||||
cdebug_log(149,0) << "AutoHorizontal::_slacken(): Source @" << DbU::getValueString(getSourcePosition()) << endl;
|
||||
cdebug_log(149,0) << "Slackened from source @" << DbU::getValueString(getSourcePosition()) << endl;
|
||||
doglegs[doglegs.size()-2]->setAxis( getSourcePosition() );
|
||||
success = true;
|
||||
|
||||
|
@ -459,8 +461,8 @@ namespace Anabatic {
|
|||
|
||||
void AutoHorizontal::updatePositions ()
|
||||
{
|
||||
_sourcePosition = _horizontal->getSourceX() - getExtensionCap();
|
||||
_targetPosition = _horizontal->getTargetX() + getExtensionCap();
|
||||
_sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
|
||||
}
|
||||
|
||||
|
||||
|
@ -480,11 +482,11 @@ namespace Anabatic {
|
|||
bool AutoHorizontal::checkPositions () const
|
||||
{
|
||||
bool coherency = true;
|
||||
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap();
|
||||
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap();
|
||||
DbU::Unit sourcePosition = _horizontal->getSourceX() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _horizontal->getTargetX() + getExtensionCap(Flags::Target);
|
||||
|
||||
if ( _sourcePosition != sourcePosition ) {
|
||||
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap()) << endl;
|
||||
cerr << "extensionCap: " << DbU::getValueString(getExtensionCap(Flags::Source)) << endl;
|
||||
cerr << "ppitch: " << DbU::getValueString(getPPitch()) << endl;
|
||||
cerr << "via width: " << DbU::getValueString(Session::getViaWidth(getLayer())) << endl;
|
||||
cerr << Error ( "%s\n Source position incoherency: "
|
||||
|
@ -792,7 +794,16 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
size_t depth = Session::getRoutingGauge()->getLayerDepth( _horizontal->getLayer() );
|
||||
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||
bool upLayer = true;
|
||||
|
||||
if (Session::getRoutingGauge()->isTwoMetals()) {
|
||||
upLayer = (depth == 0);
|
||||
} else if (Session::getRoutingGauge()->isVH()) {
|
||||
upLayer = (depth < 2);
|
||||
} else {
|
||||
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||
}
|
||||
|
||||
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
|
||||
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) );
|
||||
|
||||
|
@ -859,7 +870,7 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if (autoTarget->canDrag()) {
|
||||
if (autoTarget->canDrag() and not autoSource->canDrag()) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Horizontal);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/DataBase.h"
|
||||
#include "hurricane/Technology.h"
|
||||
#include "hurricane/ViaLayer.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
|
@ -370,6 +371,20 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::AutoSegment::CompareBySourceU".
|
||||
|
||||
|
||||
bool AutoSegment::CompareBySourceU::operator() ( AutoSegment* lhs, AutoSegment* rhs ) const
|
||||
{
|
||||
DbU::Unit deltaUnit = lhs->getSourceU() - rhs->getSourceU();
|
||||
if (deltaUnit < 0) return true; // Smallest source first.
|
||||
if (deltaUnit > 0) return false;
|
||||
|
||||
return lhs->getId() < rhs->getId(); // Smallest Id first.
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::AutoSegment".
|
||||
|
||||
|
@ -377,12 +392,55 @@ namespace Anabatic {
|
|||
size_t AutoSegment::_allocateds = 0;
|
||||
size_t AutoSegment::_globalsCount = 0;
|
||||
bool AutoSegment::_analogMode = false;
|
||||
bool AutoSegment::_initialized = false;
|
||||
vector< array<DbU::Unit*,3> > AutoSegment::_extensionCaps;
|
||||
|
||||
|
||||
void AutoSegment::setAnalogMode ( bool state ) { _analogMode = state; }
|
||||
bool AutoSegment::getAnalogMode () { return _analogMode; }
|
||||
|
||||
|
||||
void AutoSegment::_initialize ()
|
||||
{
|
||||
cerr << "AutoSegment::_initialize()" << endl;
|
||||
|
||||
_initialized = true;
|
||||
for ( size_t depth=0 ; depth<Session::getDepth() ; ++depth ) {
|
||||
DbU::Unit* viaToTopCap = new DbU::Unit ( 0 );
|
||||
DbU::Unit* viaToBottomCap = new DbU::Unit ( 0 );
|
||||
DbU::Unit* viaToSameCap = new DbU::Unit ( 0 );
|
||||
bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical());
|
||||
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
|
||||
|
||||
cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName()
|
||||
<< " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl;
|
||||
|
||||
*viaToSameCap = Session::getWireWidth(depth)/2;
|
||||
|
||||
// Bottom metal of the VIA going *up*.
|
||||
const Layer* viaLayer = dynamic_cast<const ViaLayer*>( Session::getContactLayer(depth) );
|
||||
if (viaLayer)
|
||||
*viaToTopCap = Session::getViaWidth(depth)/2 + viaLayer->getBottomEnclosure( flags );
|
||||
|
||||
// Top metal of the VIA going *down*.
|
||||
if (depth > 0) {
|
||||
viaLayer = dynamic_cast<const ViaLayer*>( Session::getContactLayer(depth-1) );
|
||||
if (viaLayer)
|
||||
*viaToBottomCap = Session::getViaWidth(depth-1)/2 + viaLayer->getTopEnclosure( flags );
|
||||
}
|
||||
|
||||
cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
|
||||
cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
|
||||
if (depth > 0)
|
||||
cerr << " viaToBottom width:" << DbU::getValueString( Session::getViaWidth(depth-1)/2 ) << endl;
|
||||
cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl;
|
||||
cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl;
|
||||
|
||||
_extensionCaps.push_back( std::array<DbU::Unit*,3>( { viaToTopCap, viaToBottomCap, viaToSameCap } ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AutoSegment::AutoSegment ( Segment* segment )
|
||||
: _id (segment->getId())
|
||||
, _gcell (NULL)
|
||||
|
@ -398,6 +456,8 @@ namespace Anabatic {
|
|||
, _parent (NULL)
|
||||
, _observers ()
|
||||
{
|
||||
if (not _initialized) _initialize();
|
||||
|
||||
_allocateds++;
|
||||
|
||||
if (dynamic_cast<Horizontal*>(segment)) setFlags( SegHorizontal );
|
||||
|
@ -544,8 +604,7 @@ namespace Anabatic {
|
|||
|
||||
cdebug_tabw(149,1);
|
||||
|
||||
updateOrient ();
|
||||
updatePositions();
|
||||
updateOrient();
|
||||
|
||||
uint64_t oldSpinFlags = _flags & SegDepthSpin;
|
||||
|
||||
|
@ -575,6 +634,8 @@ namespace Anabatic {
|
|||
incReduceds();
|
||||
}
|
||||
|
||||
updatePositions();
|
||||
|
||||
unsigned int observerFlags = Revalidate;
|
||||
if ( (_flags & SegCreated) or (oldSpinFlags != (_flags & SegDepthSpin)) )
|
||||
observerFlags |= RevalidatePPitch;
|
||||
|
@ -616,15 +677,29 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
DbU::Unit AutoSegment::getExtensionCap () const
|
||||
DbU::Unit AutoSegment::getExtensionCap ( Flags flags ) const
|
||||
{
|
||||
DbU::Unit mWidth = std::max( Session::getWireWidth(getLayer()), Session::getViaWidth(getLayer()) );
|
||||
if (getWidth() <= mWidth) return Session::getExtensionCap( getLayer() );
|
||||
return getWidth() / 2;
|
||||
#if NEW_WAY
|
||||
if (getWidth() <= mWidth) return mWidth/2 + getPitch()/2;
|
||||
return getWidth()/2 + getPitch()/2;
|
||||
#endif
|
||||
size_t depth = Session::getLayerDepth( getLayer() );
|
||||
DbU::Unit cap = 0;
|
||||
|
||||
if (flags & Flags::Source) {
|
||||
if (getFlags() & SegSourceTop ) cap = getViaToTopCap (depth);
|
||||
else if (getFlags() & SegSourceBottom) cap = getViaToBottomCap(depth);
|
||||
else cap = getViaToSameCap (depth);
|
||||
cdebug_log(159,0) << "getExtensionCap(): flags:" << getFlags()
|
||||
<< " VIA cap:" << DbU::getValueString(cap)
|
||||
<< " " << (getFlags() & SegSourceBottom)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (flags & Flags::Target) {
|
||||
if (getFlags() & SegTargetTop ) cap = getViaToTopCap (depth);
|
||||
else if (getFlags() & SegTargetBottom) cap = getViaToBottomCap(depth);
|
||||
else cap = getViaToSameCap (depth);
|
||||
}
|
||||
|
||||
if (cap < getWidth()/2) cap = getWidth()/2;
|
||||
return cap + getLayer()->getMinimalSpacing()/2;;
|
||||
}
|
||||
|
||||
|
||||
|
@ -702,6 +777,22 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void AutoSegment::getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const
|
||||
{
|
||||
cdebug_log(145,0) << "AutoSegment::getEndAxes() - " << this << endl;
|
||||
|
||||
sourceAxis = getSourceU();
|
||||
targetAxis = getTargetU();
|
||||
|
||||
if (not isNotAligned()) {
|
||||
for( AutoSegment* aligned : const_cast<AutoSegment*>(this)->getAligneds() ) {
|
||||
sourceAxis = std::min( sourceAxis, aligned->getSourceU() );
|
||||
targetAxis = std::min( targetAxis, aligned->getTargetU() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AutoSegments AutoSegment::getOnSourceContact ( Flags direction )
|
||||
{
|
||||
return AutoSegments_OnContact
|
||||
|
@ -1029,6 +1120,43 @@ namespace Anabatic {
|
|||
cdebug_log(145,0) << "Constraints: [" << DbU::getValueString(constraintMin)
|
||||
<< " " << DbU::getValueString(constraintMax) << "]" << endl;
|
||||
|
||||
AutoContact* source = getAutoSource();
|
||||
AutoContact* target = getAutoTarget();
|
||||
|
||||
if (isLocal() and source->isTurn() and target->isTurn() and not isUserDefined()) {
|
||||
AutoSegment* sourcePerpand = source->getPerpandicular(this);
|
||||
AutoSegment* targetPerpand = target->getPerpandicular(this);
|
||||
|
||||
sourcePerpand->updateOrient();
|
||||
targetPerpand->updateOrient();
|
||||
|
||||
if (not ( (sourcePerpand->getAutoSource() == source)
|
||||
xor (targetPerpand->getAutoSource() == target) ) ) {
|
||||
// This is a U-Turn.
|
||||
DbU::Unit optimal = 0;
|
||||
|
||||
if (sourcePerpand->getAutoSource() == source) {
|
||||
optimal = std::min( sourcePerpand->getTargetU(), targetPerpand->getTargetU() );
|
||||
optimal = std::min( optimal, constraintMax );
|
||||
} else {
|
||||
optimal = std::max( sourcePerpand->getSourceU(), targetPerpand->getSourceU() );
|
||||
optimal = std::max( optimal, constraintMin );
|
||||
}
|
||||
|
||||
cdebug_log(145,0) << "| Source perpandicular: " << sourcePerpand << endl;
|
||||
cdebug_log(145,0) << "| Target perpandicular: " << targetPerpand << endl;
|
||||
cdebug_log(145,0) << "Applying constraint (U-Turn) on: " << this << endl;
|
||||
cdebug_log(145,0) << "optimal: " << DbU::getValueString(optimal) << endl;
|
||||
|
||||
setOptimalMin( optimal );
|
||||
setOptimalMax( optimal );
|
||||
processeds.insert( this );
|
||||
|
||||
cdebug_tabw(145,-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserDefined()) {
|
||||
optimalMin = optimalMax = getAxis();
|
||||
aligneds.push_back( this );
|
||||
|
@ -1368,7 +1496,7 @@ namespace Anabatic {
|
|||
|
||||
bool AutoSegment::canReduce () const
|
||||
{
|
||||
if (isGlobal()) return false;
|
||||
if (isGlobal() or isDrag()) return false;
|
||||
if (not isSpinTopOrBottom()) return false;
|
||||
if (_reduceds) return false;
|
||||
|
||||
|
@ -1442,8 +1570,9 @@ namespace Anabatic {
|
|||
_changeDepth( depth, flags & ~Flags::Propagate );
|
||||
|
||||
if ((flags & Flags::Propagate) and not isNotAligned()) {
|
||||
forEach ( AutoSegment*, isegment, getAligneds(Flags::NoCheckLayer) ) {
|
||||
(*isegment)->_changeDepth( depth, flags & ~Flags::Propagate );
|
||||
cdebug_log(149,0) << "Propagate to aligneds." << endl;
|
||||
for ( AutoSegment* segment : getAligneds(Flags::NoCheckLayer) ) {
|
||||
segment->_changeDepth( depth, flags & ~Flags::Propagate );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1525,8 +1654,8 @@ namespace Anabatic {
|
|||
success = success or _slacken( flags );
|
||||
|
||||
if ((flags & Flags::Propagate) and not isNotAligned()) {
|
||||
forEach ( AutoSegment*, isegment, getAligneds() ) {
|
||||
success = success or (*isegment)->_slacken( flags );
|
||||
for ( AutoSegment* segment : getAligneds() ) {
|
||||
success = success or segment->_slacken( flags );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2135,6 +2264,7 @@ namespace Anabatic {
|
|||
{
|
||||
string state;
|
||||
state += isFixed () ?" F":" -";
|
||||
state += isFixedAxis () ? "X": "-";
|
||||
state += isUnsetAxis () ? "u": "-";
|
||||
state += isStrap () ? "S": "-";
|
||||
state += isCanonical () ? "C": "-";
|
||||
|
@ -2175,6 +2305,7 @@ namespace Anabatic {
|
|||
Record* AutoSegment::_getRecord () const
|
||||
{
|
||||
Record* record = base()->_getRecord ();
|
||||
record->add ( getSlot ( "_extensionCaps" , &_extensionCaps ) );
|
||||
record->add ( getSlot ( "_gcell" , _gcell ) );
|
||||
record->add ( getSlot ( "_id" , &_id ) );
|
||||
record->add ( getSlot ( "_flags" , &_flags ) );
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/ViaLayer.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "anabatic/Configuration.h"
|
||||
|
@ -30,6 +31,7 @@ namespace Anabatic {
|
|||
using std::max;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::ViaLayer;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -258,9 +260,11 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(149,1) << "AutoVertical::_slacken() " << this << endl;
|
||||
|
||||
if (not isDrag()) {
|
||||
if ( not isStrongTerminal()
|
||||
or (not (_flags & (SegGlobal|SegWeakGlobal)) and (getLength() < getPitch()*5)) )
|
||||
{ cdebug_tabw(149,-1); return false; }
|
||||
}
|
||||
|
||||
cdebug_log(149,0) << "_flags:" << (_flags & (SegGlobal|SegWeakGlobal)) << endl;
|
||||
cdebug_log(149,0) << "test:" << (getLength() < getPitch()*5) << endl;
|
||||
|
@ -395,8 +399,8 @@ namespace Anabatic {
|
|||
|
||||
void AutoVertical::updatePositions ()
|
||||
{
|
||||
_sourcePosition = _vertical->getSourceY() - getExtensionCap();
|
||||
_targetPosition = _vertical->getTargetY() + getExtensionCap();
|
||||
_sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
|
||||
_targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
|
||||
}
|
||||
|
||||
|
||||
|
@ -416,8 +420,8 @@ namespace Anabatic {
|
|||
bool AutoVertical::checkPositions () const
|
||||
{
|
||||
bool coherency = true;
|
||||
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap();
|
||||
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap();
|
||||
DbU::Unit sourcePosition = _vertical->getSourceY() - getExtensionCap(Flags::Source);
|
||||
DbU::Unit targetPosition = _vertical->getTargetY() + getExtensionCap(Flags::Target);
|
||||
|
||||
if ( _sourcePosition != sourcePosition ) {
|
||||
cerr << Error ( "%s\n Source position incoherency: "
|
||||
|
@ -698,7 +702,16 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
size_t depth = Session::getRoutingGauge()->getLayerDepth ( _vertical->getLayer() );
|
||||
bool upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||
bool upLayer = true;
|
||||
|
||||
if (Session::getRoutingGauge()->isTwoMetals()) {
|
||||
upLayer = (depth == 0);
|
||||
} else if (Session::getRoutingGauge()->isVH()) {
|
||||
upLayer = (depth < 2);
|
||||
} else {
|
||||
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||
}
|
||||
|
||||
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
|
||||
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) );
|
||||
|
||||
|
@ -767,7 +780,7 @@ namespace Anabatic {
|
|||
updateNativeConstraints();
|
||||
segment2->updateNativeConstraints();
|
||||
|
||||
if (autoTarget->canDrag()) {
|
||||
if (autoTarget->canDrag() and not autoSource->canDrag()) {
|
||||
Interval dragConstraints = autoTarget->getNativeUConstraints(Flags::Vertical);
|
||||
segment1->mergeUserConstraints( dragConstraints );
|
||||
|
||||
|
|
|
@ -399,7 +399,13 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(112,1) << "selectRpComponent(): " << rp << endl;
|
||||
|
||||
Box ab = rp->getCell()->getBoundingBox();
|
||||
if (rp->isAtTopLevel()) {
|
||||
cdebug_log(112,0) << "> RP is at top level, must not change it." << endl;
|
||||
cdebug_tabw(112,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
Box ab = rp->getCell()->getAbutmentBox();
|
||||
const Layer* metal1 = getLayerGauge( 0 )->getLayer();
|
||||
RoutingLayerGauge* gauge = getLayerGauge( 1 );
|
||||
Occurrence occurrence = rp->getPlugOccurrence();
|
||||
|
@ -407,8 +413,8 @@ namespace Anabatic {
|
|||
Net* masterNet = plug->getMasterNet();
|
||||
Path path = Path( occurrence.getPath(), plug->getInstance() );
|
||||
Transformation transformation = path.getTransformation();
|
||||
|
||||
Segment* current = dynamic_cast<Segment*>( rp->getOccurrence().getEntity() );
|
||||
|
||||
if (current and (current->getLayer()->getMask() != metal1->getMask())) {
|
||||
cdebug_log(112,0) << "> using default non-metal1 segment." << endl;
|
||||
cdebug_tabw(112,-1);
|
||||
|
@ -439,6 +445,11 @@ namespace Anabatic {
|
|||
, Constant::Nearest );
|
||||
minPos = bb.getXMin();
|
||||
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) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getX()) << endl;
|
||||
} else {
|
||||
trackPos = gauge->getTrackPosition( ab.getYMin()
|
||||
, ab.getYMax()
|
||||
|
@ -446,6 +457,11 @@ namespace Anabatic {
|
|||
, Constant::Nearest );
|
||||
minPos = bb.getYMin();
|
||||
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) << "bb.getCenter(): " << DbU::getValueString(bb.getCenter().getY()) << endl;
|
||||
}
|
||||
|
||||
cdebug_log(112,0) << "| " << occurrence.getPath() << endl;
|
||||
|
|
|
@ -1476,10 +1476,8 @@ namespace Anabatic {
|
|||
if (_densities[i] >= 1.0) _flags |= Flags::Saturated;
|
||||
}
|
||||
|
||||
if (ccapacity)
|
||||
_cDensity = ( (float)_contacts.size() ) / ccapacity;
|
||||
else
|
||||
_cDensity = 0;
|
||||
if (ccapacity) _cDensity = ( (float)_contacts.size() ) / ccapacity;
|
||||
else _cDensity = 0;
|
||||
_flags.reset( Flags::Invalidated );
|
||||
|
||||
checkDensity();
|
||||
|
|
|
@ -311,6 +311,8 @@ namespace Anabatic {
|
|||
|
||||
bool NetBuilderVH::_do_xG_xM1_xM3 ()
|
||||
{
|
||||
// Implicit hypothesis : we have at least two globals and at least one terminal.
|
||||
|
||||
cdebug_log(145,1) << getTypeName()
|
||||
<< "::_do_xG_" << (int)getConnexity().fields.M1
|
||||
<< "M1_" << (int)getConnexity().fields.M3
|
||||
|
@ -352,8 +354,12 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
if (north() or east()) {
|
||||
if (getRoutingPads().size() > 1) {
|
||||
rightContact = doRp_Access( getGCell(), getRoutingPads()[iLast], HAccessEW|VSmall );
|
||||
AutoSegment::create( leftContact, rightContact, Flags::Horizontal );
|
||||
} else {
|
||||
rightContact = leftContact;
|
||||
}
|
||||
|
||||
if (north() and east()) {
|
||||
setNorthEastContact( AutoContactHTee::create( getGCell(), getNet(), Session::getDContactLayer() ) );
|
||||
|
@ -517,6 +523,7 @@ namespace Anabatic {
|
|||
cdebug_tabw(145,-1);
|
||||
}
|
||||
|
||||
|
||||
string NetBuilderVH::getTypeName () const
|
||||
{ return "NetBuilderVH"; }
|
||||
|
||||
|
|
|
@ -67,7 +67,10 @@ namespace {
|
|||
cdebug_log(145,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;
|
||||
|
||||
set<AutoSegment*> verticalSegments;
|
||||
set<AutoSegment*> horizontalSegments;
|
||||
|
@ -87,9 +90,6 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
Box constraintBox = sourceContact->getConstraintBox();
|
||||
cdebug_log(145,0) << "Contraint: " << constraintBox << endl;
|
||||
|
||||
// Propagate constraint through horizontally aligned segments.
|
||||
cdebug_log(145,0) << "Propagate constraint on horizontal segments" << endl;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/Cell.h"
|
||||
|
@ -47,6 +48,7 @@ namespace Anabatic {
|
|||
using namespace std;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::ForEachIterator;
|
||||
using Hurricane::UpdateSession;
|
||||
using Hurricane::Horizontal;
|
||||
|
@ -158,6 +160,7 @@ namespace Anabatic {
|
|||
|
||||
canonical->setFlags( AutoSegment::SegCanonical );
|
||||
cdebug_log(145,0) << "Canonical: " << canonical << endl;
|
||||
Interval userConstraints = canonical->getUserConstraints();
|
||||
|
||||
for ( size_t j=0 ; j<aligneds.size() ; j++ ) {
|
||||
if (isWeakGlobal and not aligneds[j]->isGlobal()) aligneds[j]->setFlags ( AutoSegment::SegWeakGlobal );
|
||||
|
@ -171,10 +174,23 @@ namespace Anabatic {
|
|||
}
|
||||
aligneds[j]->unsetFlags( AutoSegment::SegCanonical );
|
||||
cdebug_log(145,0) << "Secondary: " << aligneds[j] << endl;
|
||||
|
||||
userConstraints.intersection( aligneds[j]->getUserConstraints() );
|
||||
}
|
||||
if (aligneds.empty()) canonical->setFlags( AutoSegment::SegNotAligned );
|
||||
|
||||
if (not getRoutingGauge()->isSymbolic()
|
||||
and (userConstraints.getSize() < Session::getPitch(1)*2) ) {
|
||||
cerr << Warning( "Session::_canonize(): On %s\n"
|
||||
" Combined user constraints are too tight [%s : %s]."
|
||||
, getString(canonical).c_str()
|
||||
, DbU::getValueString(userConstraints.getVMin()).c_str()
|
||||
, DbU::getValueString(userConstraints.getVMax()).c_str()
|
||||
) << endl;
|
||||
}
|
||||
|
||||
cdebug_log(149,0) << "Align on canonical:" << canonical << endl;
|
||||
cdebug_log(145,0) << "Combined user constraints: " << userConstraints << endl;
|
||||
|
||||
//canonical->setAxis( canonical->getAxis(), Flags::Realignate );
|
||||
if (canonical->isUnsetAxis() and not canonical->isFixed())
|
||||
|
@ -194,21 +210,19 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(145,1) << "Anabatic::Session::_revalidateTopology()" << endl;
|
||||
|
||||
set<Net*>::iterator inet = _netInvalidateds.begin();
|
||||
|
||||
for ( ; inet != _netInvalidateds.end() ; inet++ ) {
|
||||
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << *inet << endl;
|
||||
_anabatic->updateNetTopology ( *inet );
|
||||
_anabatic->computeNetConstraints( *inet );
|
||||
_anabatic->_computeNetOptimals ( *inet );
|
||||
_anabatic->_computeNetTerminals ( *inet );
|
||||
for ( Net* net : _netInvalidateds ) {
|
||||
cdebug_log(145,0) << "Anabatic::Session::_revalidateTopology(Net*)" << net << endl;
|
||||
_anabatic->updateNetTopology ( net );
|
||||
_anabatic->computeNetConstraints( net );
|
||||
_anabatic->_computeNetOptimals ( net );
|
||||
_anabatic->_computeNetTerminals ( net );
|
||||
}
|
||||
_canonize ();
|
||||
|
||||
for ( size_t i=0 ; i<_segmentInvalidateds.size() ; ++i ) {
|
||||
if (_segmentInvalidateds[i]->isCanonical()) {
|
||||
if (_segmentInvalidateds[i]->isUnsetAxis()) _segmentInvalidateds[i]->toOptimalAxis();
|
||||
else _segmentInvalidateds[i]->toConstraintAxis();
|
||||
for ( AutoSegment* segment : _segmentInvalidateds ) {
|
||||
if (segment->isCanonical()) {
|
||||
if (segment->isUnsetAxis()) segment->toOptimalAxis();
|
||||
else segment->toConstraintAxis();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,646 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | A n a b a t i c - Routing Toolbox |
|
||||
// | |
|
||||
// | Author : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./anabatic/AutoSegment.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef ANABATIC_AUTOSEGMENT_H
|
||||
#define ANABATIC_AUTOSEGMENT_H
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include "hurricane/Interval.h"
|
||||
#include "hurricane/Segment.h"
|
||||
#include "hurricane/Components.h"
|
||||
#include "hurricane/Contact.h"
|
||||
namespace Hurricane {
|
||||
class Layer;
|
||||
class Horizontal;
|
||||
class Vertical;
|
||||
class Cell;
|
||||
}
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "anabatic/Constants.h"
|
||||
#include "anabatic/GCell.h"
|
||||
#include "anabatic/AutoSegments.h"
|
||||
#include "anabatic/Session.h"
|
||||
|
||||
|
||||
namespace Anabatic {
|
||||
|
||||
using std::array;
|
||||
using std::set;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::binary_function;
|
||||
using Hurricane::StaticObservable;
|
||||
using Hurricane::BaseObserver;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::Interval;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::Components;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::Cell;
|
||||
using CRL::RoutingGauge;
|
||||
|
||||
class AutoHorizontal;
|
||||
class AutoVertical;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "AutoSegment".
|
||||
|
||||
|
||||
|
||||
class AutoSegment {
|
||||
friend class AutoHorizontal;
|
||||
friend class AutoVertical;
|
||||
|
||||
public:
|
||||
static const uint64_t SegNoFlags = 0L;
|
||||
static const uint64_t SegHorizontal = (1L<< 0);
|
||||
static const uint64_t SegFixed = (1L<< 1);
|
||||
static const uint64_t SegFixedAxis = (1L<< 2);
|
||||
static const uint64_t SegGlobal = (1L<< 3);
|
||||
static const uint64_t SegWeakGlobal = (1L<< 4);
|
||||
static const uint64_t SegLongLocal = (1L<< 5);
|
||||
static const uint64_t SegCanonical = (1L<< 6);
|
||||
static const uint64_t SegBipoint = (1L<< 7);
|
||||
static const uint64_t SegDogleg = (1L<< 8);
|
||||
static const uint64_t SegStrap = (1L<< 9);
|
||||
static const uint64_t SegSourceTop = (1L<<10);
|
||||
static const uint64_t SegSourceBottom = (1L<<11);
|
||||
static const uint64_t SegTargetTop = (1L<<12);
|
||||
static const uint64_t SegTargetBottom = (1L<<13);
|
||||
static const uint64_t SegIsReduced = (1L<<14);
|
||||
static const uint64_t SegDrag = (1L<<15);
|
||||
static const uint64_t SegLayerChange = (1L<<16);
|
||||
static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal.
|
||||
static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal.
|
||||
static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal;
|
||||
static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
|
||||
static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
|
||||
static const uint64_t SegNotSourceAligned = (1L<<21);
|
||||
static const uint64_t SegNotTargetAligned = (1L<<22);
|
||||
static const uint64_t SegUnbound = (1L<<23);
|
||||
static const uint64_t SegHalfSlackened = (1L<<24);
|
||||
static const uint64_t SegSlackened = (1L<<25);
|
||||
static const uint64_t SegAxisSet = (1L<<26);
|
||||
static const uint64_t SegInvalidated = (1L<<27);
|
||||
static const uint64_t SegInvalidatedSource = (1L<<28);
|
||||
static const uint64_t SegInvalidatedTarget = (1L<<29);
|
||||
static const uint64_t SegInvalidatedLayer = (1L<<30);
|
||||
static const uint64_t SegCreated = (1L<<31);
|
||||
static const uint64_t SegUserDefined = (1L<<32);
|
||||
static const uint64_t SegAnalog = (1L<<33);
|
||||
static const uint64_t SegWide = (1L<<34);
|
||||
// Masks.
|
||||
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
|
||||
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
|
||||
static const uint64_t SegSpinTop = SegSourceTop |SegTargetTop;
|
||||
static const uint64_t SegSpinBottom = SegSourceBottom |SegTargetBottom;
|
||||
static const uint64_t SegDepthSpin = SegSpinTop |SegSpinBottom;
|
||||
|
||||
public:
|
||||
class Observable : public StaticObservable<1> {
|
||||
public:
|
||||
enum Indexes { TrackSegment = 0
|
||||
};
|
||||
public:
|
||||
inline Observable ();
|
||||
private:
|
||||
Observable ( const StaticObservable& );
|
||||
Observable& operator= ( const StaticObservable& );
|
||||
};
|
||||
public:
|
||||
enum ObserverFlag { Create = (1 << 0)
|
||||
, Destroy = (1 << 1)
|
||||
, Invalidate = (1 << 2)
|
||||
, Revalidate = (1 << 3)
|
||||
, RevalidatePPitch = (1 << 4)
|
||||
};
|
||||
public:
|
||||
typedef std::function< void(AutoSegment*) > RevalidateCb_t;
|
||||
public:
|
||||
static void setAnalogMode ( bool );
|
||||
static bool getAnalogMode ();
|
||||
inline static DbU::Unit getViaToTopCap ( size_t depth );
|
||||
inline static DbU::Unit getViaToBottomCap ( size_t depth );
|
||||
inline static DbU::Unit getViaToSameCap ( size_t depth );
|
||||
static AutoSegment* create ( AutoContact* source
|
||||
, AutoContact* target
|
||||
, Segment* hurricaneSegment
|
||||
);
|
||||
static AutoSegment* create ( AutoContact* source
|
||||
, AutoContact* target
|
||||
, Flags dir
|
||||
, size_t depth=RoutingGauge::nlayerdepth
|
||||
);
|
||||
void destroy ();
|
||||
// Wrapped Segment Functions.
|
||||
virtual Segment* base () const = 0;
|
||||
virtual Segment* base () = 0;
|
||||
virtual Horizontal* getHorizontal () { return NULL; };
|
||||
virtual Vertical* getVertical () { return NULL; };
|
||||
inline Cell* getCell () const;
|
||||
inline Net* getNet () const;
|
||||
inline const Layer* getLayer () const;
|
||||
inline Box getBoundingBox () const;
|
||||
inline Hook* getSourceHook ();
|
||||
inline Hook* getTargetHook ();
|
||||
inline Contact* getSource () const;
|
||||
inline Contact* getTarget () const;
|
||||
inline Component* getOppositeAnchor ( Component* ) const;
|
||||
inline Components getAnchors () const;
|
||||
virtual DbU::Unit getX () const;
|
||||
virtual DbU::Unit getY () const;
|
||||
inline DbU::Unit getWidth () const;
|
||||
inline DbU::Unit getContactWidth () const;
|
||||
inline DbU::Unit getLength () const;
|
||||
inline DbU::Unit getSourcePosition () const;
|
||||
inline DbU::Unit getTargetPosition () const;
|
||||
inline DbU::Unit getSourceX () const;
|
||||
inline DbU::Unit getSourceY () const;
|
||||
inline DbU::Unit getTargetX () const;
|
||||
inline DbU::Unit getTargetY () const;
|
||||
inline void invert ();
|
||||
inline void setLayer ( const Layer* );
|
||||
// Predicates.
|
||||
inline bool isHorizontal () const;
|
||||
inline bool isVertical () const;
|
||||
inline bool isGlobal () const;
|
||||
inline bool isWeakGlobal () const;
|
||||
inline bool isLongLocal () const;
|
||||
inline bool isLocal () const;
|
||||
inline bool isFixed () const;
|
||||
inline bool isFixedAxis () const;
|
||||
inline bool isBipoint () const;
|
||||
inline bool isWeakTerminal () const;
|
||||
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;
|
||||
bool isStrongTerminal ( Flags flags=Flags::NoFlags ) const;
|
||||
inline bool isSourceTerminal () const;
|
||||
inline bool isTargetTerminal () const;
|
||||
inline bool isLayerChange () const;
|
||||
inline bool isSpinTop () const;
|
||||
inline bool isSpinBottom () const;
|
||||
inline bool isSpinTopOrBottom () const;
|
||||
inline bool isReduced () const;
|
||||
inline bool isStrap () const;
|
||||
inline bool isDogleg () const;
|
||||
inline bool isUnbound () const;
|
||||
inline bool isInvalidated () const;
|
||||
inline bool isInvalidatedLayer () const;
|
||||
inline bool isCreated () const;
|
||||
inline bool isCanonical () const;
|
||||
inline bool isUnsetAxis () const;
|
||||
inline bool isSlackened () const;
|
||||
inline bool isUserDefined () const;
|
||||
bool isReduceCandidate () const;
|
||||
bool isUTurn () const;
|
||||
inline bool isAnalog () const;
|
||||
inline bool isWide () const;
|
||||
virtual bool _canSlacken () const = 0;
|
||||
bool canReduce () const;
|
||||
bool mustRaise () const;
|
||||
Flags canDogleg ( Interval );
|
||||
virtual bool canMoveULeft ( float reserve=0.0 ) const = 0;
|
||||
virtual bool canMoveURight ( float reserve=0.0 ) const = 0;
|
||||
bool canMoveUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
|
||||
bool canPivotUp ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
|
||||
bool canPivotDown ( float reserve=0.0, Flags flags=Flags::NoFlags ) const;
|
||||
bool canSlacken ( Flags flags=Flags::NoFlags ) const;
|
||||
virtual bool checkPositions () const = 0;
|
||||
virtual bool checkConstraints () const = 0;
|
||||
bool checkDepthSpin () const;
|
||||
// Accessors.
|
||||
inline unsigned long getId () const;
|
||||
inline uint64_t getFlags () const;
|
||||
virtual Flags getDirection () const = 0;
|
||||
inline GCell* getGCell () const;
|
||||
virtual bool getGCells ( vector<GCell*>& ) const = 0;
|
||||
inline AutoContact* getAutoSource () const;
|
||||
inline AutoContact* getAutoTarget () const;
|
||||
AutoContact* getOppositeAnchor ( AutoContact* ) const;
|
||||
size_t getPerpandicularsBound ( set<AutoSegment*>& );
|
||||
inline AutoSegment* getParent () const;
|
||||
inline unsigned int getDepth () const;
|
||||
inline DbU::Unit getPitch () const;
|
||||
DbU::Unit getPPitch () const;
|
||||
#if DISABLED
|
||||
DbU::Unit getExtensionCap () const;
|
||||
#endif
|
||||
DbU::Unit getExtensionCap ( Flags ) const;
|
||||
inline DbU::Unit getAxis () const;
|
||||
void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
|
||||
virtual DbU::Unit getSourceU () const = 0;
|
||||
virtual DbU::Unit getTargetU () const = 0;
|
||||
virtual DbU::Unit getDuSource () const = 0;
|
||||
virtual DbU::Unit getDuTarget () const = 0;
|
||||
inline DbU::Unit getOrigin () const;
|
||||
inline DbU::Unit getExtremity () const;
|
||||
virtual Interval getSpanU () const = 0;
|
||||
Interval getMinSpanU () const;
|
||||
virtual Interval getSourceConstraints ( Flags flags=Flags::NoFlags ) const = 0;
|
||||
virtual Interval getTargetConstraints ( Flags flags=Flags::NoFlags ) const = 0;
|
||||
virtual bool getConstraints ( DbU::Unit& min, DbU::Unit& max ) const = 0;
|
||||
inline bool getConstraints ( Interval& i ) const;
|
||||
inline const Interval& getUserConstraints () const;
|
||||
inline const Interval& getNativeConstraints () const;
|
||||
virtual DbU::Unit getSlack () const;
|
||||
inline DbU::Unit getOptimalMin () const;
|
||||
inline DbU::Unit getOptimalMax () const;
|
||||
inline DbU::Unit getNativeMin () const;
|
||||
inline DbU::Unit getNativeMax () const;
|
||||
Interval& getOptimal ( Interval& i ) const;
|
||||
virtual DbU::Unit getCost ( DbU::Unit axis ) const;
|
||||
virtual AutoSegment* getCanonical ( DbU::Unit& min , DbU::Unit& max );
|
||||
inline AutoSegment* getCanonical ( Interval& i );
|
||||
float getMaxUnderDensity ( Flags flags );
|
||||
// Modifiers.
|
||||
inline void unsetFlags ( uint64_t );
|
||||
inline void setFlags ( uint64_t );
|
||||
void setFlagsOnAligneds ( uint64_t );
|
||||
inline void incReduceds ();
|
||||
inline void decReduceds ();
|
||||
virtual void setDuSource ( DbU::Unit du ) = 0;
|
||||
virtual void setDuTarget ( DbU::Unit du ) = 0;
|
||||
void computeTerminal ();
|
||||
virtual void updateOrient () = 0;
|
||||
virtual void updatePositions () = 0;
|
||||
virtual void updateNativeConstraints () = 0;
|
||||
void updateSourceSpin ();
|
||||
void updateTargetSpin ();
|
||||
void sourceDetach ();
|
||||
void targetDetach ();
|
||||
void sourceAttach ( AutoContact* );
|
||||
void targetAttach ( AutoContact* );
|
||||
//inline void mergeUserConstraints ( const Interval& );
|
||||
void mergeUserConstraints ( const Interval& );
|
||||
inline void resetUserConstraints ();
|
||||
inline void setOptimalMin ( DbU::Unit min );
|
||||
inline void setOptimalMax ( DbU::Unit max );
|
||||
inline void mergeNativeMin ( DbU::Unit min );
|
||||
inline void mergeNativeMax ( DbU::Unit max );
|
||||
inline void resetNativeConstraints ( DbU::Unit min, DbU::Unit max );
|
||||
bool checkNotInvalidated () const;
|
||||
inline void setParent ( AutoSegment* );
|
||||
void revalidate ();
|
||||
AutoSegment* makeDogleg ( AutoContact* );
|
||||
Flags makeDogleg ( Interval, Flags flags=Flags::NoFlags );
|
||||
Flags makeDogleg ( GCell* , Flags flags=Flags::NoFlags );
|
||||
virtual Flags _makeDogleg ( GCell* , Flags flags ) = 0;
|
||||
virtual bool moveULeft () = 0;
|
||||
virtual bool moveURight () = 0;
|
||||
bool slacken ( Flags flags );
|
||||
virtual bool _slacken ( Flags flags ) = 0;
|
||||
void _changeDepth ( unsigned int depth, Flags flags );
|
||||
void changeDepth ( unsigned int depth, Flags flags );
|
||||
bool moveUp ( Flags flags=Flags::NoFlags );
|
||||
bool moveDown ( Flags flags=Flags::NoFlags );
|
||||
bool reduceDoglegLayer ();
|
||||
bool reduce ();
|
||||
bool raise ();
|
||||
// Canonical Modifiers.
|
||||
AutoSegment* canonize ( Flags flags=Flags::NoFlags );
|
||||
virtual void invalidate ( Flags flags=Flags::Propagate );
|
||||
void invalidate ( AutoContact* );
|
||||
void computeOptimal ( set<AutoSegment*>& processeds );
|
||||
void setAxis ( DbU::Unit, Flags flags=Flags::NoFlags );
|
||||
bool toConstraintAxis ( Flags flags=Flags::Realignate );
|
||||
bool toOptimalAxis ( Flags flags=Flags::Realignate );
|
||||
// Collections & Filters.
|
||||
AutoSegments getOnSourceContact ( Flags direction );
|
||||
AutoSegments getOnTargetContact ( Flags direction );
|
||||
AutoSegments getCachedOnSourceContact ( Flags direction );
|
||||
AutoSegments getCachedOnTargetContact ( Flags direction );
|
||||
AutoSegments getAligneds ( Flags flags=Flags::NoFlags );
|
||||
AutoSegments getConnecteds ( Flags flags=Flags::NoFlags );
|
||||
AutoSegments getPerpandiculars ( Flags flags=Flags::NoFlags );
|
||||
size_t getAlignedContacts ( map<AutoContact*,int>& ) const ;
|
||||
// Observers.
|
||||
template< typename OwnerT >
|
||||
inline OwnerT* getObserver ( size_t slot );
|
||||
inline void setObserver ( size_t slot, BaseObserver* );
|
||||
inline void notify ( unsigned int flags );
|
||||
// Inspector Management.
|
||||
virtual Record* _getRecord () const = 0;
|
||||
virtual string _getString () const = 0;
|
||||
virtual string _getTypeName () const = 0;
|
||||
// Non-reviewed atomic modifiers.
|
||||
bool _check () const;
|
||||
#if THIS_IS_DISABLED
|
||||
virtual void desalignate ( AutoContact* ) = 0;
|
||||
bool shearUp ( GCell*
|
||||
, AutoSegment*& movedUp
|
||||
, float reserve
|
||||
, Flags flags );
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Internal: Static Attributes.
|
||||
static size_t _allocateds;
|
||||
static size_t _globalsCount;
|
||||
static bool _analogMode;
|
||||
static bool _initialized;
|
||||
static vector< array<DbU::Unit*,3> > _extensionCaps;
|
||||
// Internal: Attributes.
|
||||
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;
|
||||
DbU::Unit _sourcePosition;
|
||||
DbU::Unit _targetPosition;
|
||||
Interval _userConstraints;
|
||||
Interval _nativeConstraints;
|
||||
AutoSegment* _parent;
|
||||
Observable _observers;
|
||||
|
||||
// Internal: Constructors & Destructors.
|
||||
protected:
|
||||
AutoSegment ( Segment* segment );
|
||||
virtual ~AutoSegment ();
|
||||
static void _preCreate ( AutoContact* source, AutoContact* target );
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
static void _initialize ();
|
||||
private:
|
||||
AutoSegment ( const AutoSegment& );
|
||||
AutoSegment& operator= ( const AutoSegment& );
|
||||
protected:
|
||||
void _invalidate ();
|
||||
inline uint64_t _getFlags () const;
|
||||
std::string _getStringFlags () const;
|
||||
virtual void _setAxis ( DbU::Unit ) = 0;
|
||||
|
||||
public:
|
||||
struct CompareId : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
inline bool operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
struct CompareByDepthLength : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
|
||||
typedef std::set<AutoSegment*,CompareId> IdSet;
|
||||
|
||||
// Static Utilities.
|
||||
public:
|
||||
static inline uint64_t swapSourceTargetFlags ( AutoSegment* );
|
||||
static inline bool areAlignedsAndDiffLayer ( AutoSegment*, AutoSegment* );
|
||||
static AutoSegment* getGlobalThroughDogleg ( AutoSegment* dogleg, AutoContact* from );
|
||||
static bool isTopologicalBound ( AutoSegment* seed, Flags flags );
|
||||
static inline bool arePerpandiculars ( AutoSegment* a, AutoSegment* b );
|
||||
static inline bool arePerpandiculars ( bool isHorizontalA, AutoSegment* b );
|
||||
static inline bool areAligneds ( AutoSegment* a, AutoSegment* b );
|
||||
static Flags getPerpandicularState ( AutoContact* contact
|
||||
, AutoSegment* source
|
||||
, AutoSegment* current
|
||||
, bool isHorizontalMaster
|
||||
, const Layer* masterLayer=NULL
|
||||
);
|
||||
static inline Flags getPerpandicularState ( AutoContact* contact
|
||||
, AutoSegment* source
|
||||
, AutoSegment* current
|
||||
, AutoSegment* master
|
||||
);
|
||||
static void getTopologicalInfos ( AutoSegment* seed
|
||||
, vector<AutoSegment*>& collapseds
|
||||
, vector<AutoSegment*>& perpandiculars
|
||||
, DbU::Unit& leftBound
|
||||
, DbU::Unit& rightBound
|
||||
);
|
||||
static int getTerminalCount ( AutoSegment* seed
|
||||
, vector<AutoSegment*>& collapseds
|
||||
);
|
||||
static inline int getTerminalCount ( AutoSegment* seed );
|
||||
static inline size_t getGlobalsCount ();
|
||||
static inline size_t getAllocateds ();
|
||||
static inline unsigned long getMaxId ();
|
||||
};
|
||||
|
||||
|
||||
// Inline Functions.
|
||||
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; }
|
||||
inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
|
||||
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
|
||||
inline unsigned long AutoSegment::getId () const { return _id; }
|
||||
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
|
||||
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
|
||||
inline const Layer* AutoSegment::getLayer () const { return base()->getLayer(); }
|
||||
inline Box AutoSegment::getBoundingBox () const { return base()->getBoundingBox(); }
|
||||
inline Hook* AutoSegment::getSourceHook () { return base()->getSourceHook(); }
|
||||
inline Hook* AutoSegment::getTargetHook () { return base()->getTargetHook(); }
|
||||
inline Contact* AutoSegment::getSource () const { return static_cast<Contact*>(base()->getSource()); }
|
||||
inline Contact* AutoSegment::getTarget () const { return static_cast<Contact*>(base()->getTarget()); }
|
||||
inline Component* AutoSegment::getOppositeAnchor ( Component* anchor ) const { return base()->getOppositeAnchor(anchor); };
|
||||
inline AutoSegment* AutoSegment::getParent () const { return _parent; }
|
||||
inline DbU::Unit AutoSegment::getSourcePosition () const { return _sourcePosition; }
|
||||
inline DbU::Unit AutoSegment::getTargetPosition () const { return _targetPosition; }
|
||||
inline DbU::Unit AutoSegment::getSourceX () const { return base()->getSourceX(); }
|
||||
inline DbU::Unit AutoSegment::getSourceY () const { return base()->getSourceY(); }
|
||||
inline DbU::Unit AutoSegment::getTargetX () const { return base()->getTargetX(); }
|
||||
inline DbU::Unit AutoSegment::getTargetY () const { return base()->getTargetY(); }
|
||||
inline DbU::Unit AutoSegment::getWidth () const { return base()->getWidth(); }
|
||||
inline DbU::Unit AutoSegment::getLength () const { return base()->getLength(); }
|
||||
inline void AutoSegment::invert () { base()->invert(); }
|
||||
inline GCell* AutoSegment::getGCell () const { return _gcell; }
|
||||
inline AutoContact* AutoSegment::getAutoSource () const { return Session::lookup(getSource()); }
|
||||
inline AutoContact* AutoSegment::getAutoTarget () const { return Session::lookup(getTarget()); }
|
||||
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 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(); }
|
||||
inline DbU::Unit AutoSegment::getExtremity () const { return isHorizontal()?_gcell->getYMax():_gcell->getXMax(); }
|
||||
inline DbU::Unit AutoSegment::getOptimalMin () const { return DbU::lambda(_optimalMin) + getOrigin(); }
|
||||
inline DbU::Unit AutoSegment::getOptimalMax () const { return DbU::lambda(_optimalMax) + getOrigin(); }
|
||||
inline DbU::Unit AutoSegment::getNativeMin () const { return _nativeConstraints.getVMin(); }
|
||||
inline DbU::Unit AutoSegment::getNativeMax () const { return _nativeConstraints.getVMax(); }
|
||||
inline const Interval& AutoSegment::getUserConstraints () const { return _userConstraints; }
|
||||
inline const Interval& AutoSegment::getNativeConstraints () const { return _nativeConstraints; }
|
||||
|
||||
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
|
||||
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
|
||||
inline bool AutoSegment::isFixed () const { return _flags & SegFixed; }
|
||||
inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; }
|
||||
inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; }
|
||||
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::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::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; }
|
||||
inline bool AutoSegment::isDogleg () const { return _flags & SegDogleg ; }
|
||||
inline bool AutoSegment::isUnbound () const { return _flags & SegUnbound ; }
|
||||
inline bool AutoSegment::isStrap () const { return _flags & SegStrap; }
|
||||
inline bool AutoSegment::isLayerChange () const { return _flags & SegLayerChange; }
|
||||
inline bool AutoSegment::isSpinTop () const { return ((_flags & SegSpinTop ) == SegSpinTop); }
|
||||
inline bool AutoSegment::isSpinBottom () const { return ((_flags & SegSpinBottom) == SegSpinBottom); }
|
||||
inline bool AutoSegment::isSpinTopOrBottom () const { return isSpinTop() or isSpinBottom(); }
|
||||
inline bool AutoSegment::isReduced () const { return _flags & SegIsReduced; }
|
||||
inline bool AutoSegment::isSlackened () const { return _flags & SegSlackened; }
|
||||
inline bool AutoSegment::isCanonical () const { return _flags & SegCanonical; }
|
||||
inline bool AutoSegment::isUnsetAxis () const { return not (_flags & SegAxisSet); }
|
||||
inline bool AutoSegment::isInvalidated () const { return _flags & SegInvalidated; }
|
||||
inline bool AutoSegment::isInvalidatedLayer () const { return _flags & SegInvalidatedLayer; }
|
||||
inline bool AutoSegment::isCreated () const { return _flags & SegCreated; }
|
||||
inline bool AutoSegment::isUserDefined () const { return _flags & SegUserDefined; }
|
||||
inline bool AutoSegment::isAnalog () const { return _flags & SegAnalog; }
|
||||
inline bool AutoSegment::isWide () const { return _flags & SegWide; }
|
||||
inline void AutoSegment::setFlags ( uint64_t flags ) { _flags |= flags; }
|
||||
inline void AutoSegment::unsetFlags ( uint64_t flags ) { _flags &= ~flags; }
|
||||
|
||||
inline uint64_t AutoSegment::getFlags () const { return _flags; }
|
||||
inline uint64_t AutoSegment::_getFlags () const { return _flags; }
|
||||
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; }
|
||||
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
|
||||
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
|
||||
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
|
||||
inline void AutoSegment::mergeNativeMax ( DbU::Unit max ) { _nativeConstraints.getVMax() = std::min( max, _nativeConstraints.getVMax() ); }
|
||||
inline void AutoSegment::resetNativeConstraints ( DbU::Unit min, DbU::Unit max ) { _nativeConstraints = Interval( min, max ); }
|
||||
//inline void AutoSegment::mergeUserConstraints ( const Interval& constraints ) { _userConstraints.intersection(constraints); }
|
||||
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
|
||||
|
||||
|
||||
inline DbU::Unit AutoSegment::getContactWidth () const
|
||||
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
|
||||
|
||||
|
||||
inline void AutoSegment::setParent ( AutoSegment* parent )
|
||||
{
|
||||
if ( parent == this ) {
|
||||
cerr << "Parentage Looping: " << parent->_getString() << endl;
|
||||
}
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
|
||||
{ return lhs->getId() < rhs->getId(); }
|
||||
|
||||
inline uint64_t AutoSegment::swapSourceTargetFlags ( AutoSegment* segment )
|
||||
{
|
||||
uint64_t segFlags = segment->getFlags();
|
||||
uint64_t swapFlags = segment->getFlags() & ~(SegSourceTop |SegTargetTop
|
||||
|SegSourceBottom |SegTargetBottom
|
||||
|SegSourceTerminal |SegTargetTerminal
|
||||
|SegNotSourceAligned |SegNotTargetAligned
|
||||
|SegInvalidatedSource|SegInvalidatedTarget
|
||||
);
|
||||
|
||||
swapFlags |= (segFlags & SegSourceTop ) ? SegTargetTop : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegSourceBottom ) ? SegTargetBottom : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegSourceTerminal ) ? SegTargetTerminal : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegNotSourceAligned ) ? SegNotTargetAligned : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegInvalidatedSource) ? SegInvalidatedTarget : SegNoFlags;
|
||||
|
||||
swapFlags |= (segFlags & SegTargetTop ) ? SegSourceTop : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegTargetBottom ) ? SegSourceBottom : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegTargetTerminal ) ? SegSourceTerminal : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegNotTargetAligned ) ? SegNotSourceAligned : SegNoFlags;
|
||||
swapFlags |= (segFlags & SegInvalidatedTarget) ? SegInvalidatedSource : SegNoFlags;
|
||||
return swapFlags;
|
||||
}
|
||||
|
||||
inline bool AutoSegment::areAlignedsAndDiffLayer ( AutoSegment* s1, AutoSegment* s2 )
|
||||
{ return s1 and s2
|
||||
and (s1->isHorizontal() == s2->isHorizontal())
|
||||
and (s1->getLayer() != s2->getLayer()); }
|
||||
|
||||
inline bool AutoSegment::arePerpandiculars ( AutoSegment* a, AutoSegment* b )
|
||||
{ return a and b and (a->isHorizontal() != b->isHorizontal()); }
|
||||
|
||||
inline bool AutoSegment::arePerpandiculars ( bool isHorizontalA, AutoSegment* b )
|
||||
{ return b and (isHorizontalA != b->isHorizontal()); }
|
||||
|
||||
inline bool AutoSegment::areAligneds ( AutoSegment* a, AutoSegment* b )
|
||||
{ return a and b and (a->isHorizontal() == b->isHorizontal()); }
|
||||
|
||||
inline Flags AutoSegment::getPerpandicularState ( AutoContact* contact
|
||||
, AutoSegment* source
|
||||
, AutoSegment* current
|
||||
, AutoSegment* master )
|
||||
{
|
||||
return getPerpandicularState ( contact, source, current, master->isHorizontal(), master->getLayer() );
|
||||
}
|
||||
|
||||
|
||||
inline int AutoSegment::getTerminalCount ( AutoSegment* seed )
|
||||
{
|
||||
cdebug_log(145,0) << "getTerminalCount() - " << seed << endl;
|
||||
|
||||
vector<AutoSegment*> collapseds;
|
||||
vector<AutoSegment*> perpandiculars;
|
||||
DbU::Unit leftBound;
|
||||
DbU::Unit rightBound;
|
||||
|
||||
getTopologicalInfos ( seed
|
||||
, collapseds
|
||||
, perpandiculars
|
||||
, leftBound
|
||||
, rightBound
|
||||
);
|
||||
|
||||
return getTerminalCount ( seed, collapseds );
|
||||
}
|
||||
|
||||
|
||||
inline size_t AutoSegment::getGlobalsCount () { return _globalsCount; }
|
||||
inline size_t AutoSegment::getAllocateds () { return _allocateds; }
|
||||
|
||||
|
||||
inline void AutoSegment::setObserver ( size_t slot, BaseObserver* observer )
|
||||
{ _observers.setObserver( slot, observer ); }
|
||||
|
||||
template<typename OwnerT>
|
||||
inline OwnerT* AutoSegment::getObserver ( size_t slot )
|
||||
{ return _observers.getObserver<OwnerT>(slot); }
|
||||
|
||||
inline void AutoSegment::notify ( unsigned int flags )
|
||||
{ _observers.notify( flags ); }
|
||||
|
||||
inline AutoSegment::Observable::Observable () : StaticObservable<1>() { }
|
||||
|
||||
|
||||
} // End of Anabatic namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Anabatic::AutoSegment);
|
||||
|
||||
|
||||
# endif // ANABATIC_AUTOSEGMENT_H
|
|
@ -216,6 +216,7 @@ namespace Anabatic {
|
|||
// Global routing related functions.
|
||||
void globalRoute ();
|
||||
void cleanupGlobal ();
|
||||
void relaxOverConstraineds ();
|
||||
// Detailed routing related functions.
|
||||
inline bool isInDemoMode () const;
|
||||
inline bool isChip () const;
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace Hurricane {
|
|||
|
||||
namespace Anabatic {
|
||||
|
||||
using std::array;
|
||||
using std::set;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
@ -70,39 +71,40 @@ namespace Anabatic {
|
|||
static const uint64_t SegNoFlags = 0L;
|
||||
static const uint64_t SegHorizontal = (1L<< 0);
|
||||
static const uint64_t SegFixed = (1L<< 1);
|
||||
static const uint64_t SegGlobal = (1L<< 2);
|
||||
static const uint64_t SegWeakGlobal = (1L<< 3);
|
||||
static const uint64_t SegLongLocal = (1L<< 4);
|
||||
static const uint64_t SegCanonical = (1L<< 5);
|
||||
static const uint64_t SegBipoint = (1L<< 6);
|
||||
static const uint64_t SegDogleg = (1L<< 7);
|
||||
static const uint64_t SegStrap = (1L<< 8);
|
||||
static const uint64_t SegSourceTop = (1L<< 9);
|
||||
static const uint64_t SegSourceBottom = (1L<<10);
|
||||
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 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 SegFixedAxis = (1L<< 2);
|
||||
static const uint64_t SegGlobal = (1L<< 3);
|
||||
static const uint64_t SegWeakGlobal = (1L<< 4);
|
||||
static const uint64_t SegLongLocal = (1L<< 5);
|
||||
static const uint64_t SegCanonical = (1L<< 6);
|
||||
static const uint64_t SegBipoint = (1L<< 7);
|
||||
static const uint64_t SegDogleg = (1L<< 8);
|
||||
static const uint64_t SegStrap = (1L<< 9);
|
||||
static const uint64_t SegSourceTop = (1L<<10);
|
||||
static const uint64_t SegSourceBottom = (1L<<11);
|
||||
static const uint64_t SegTargetTop = (1L<<12);
|
||||
static const uint64_t SegTargetBottom = (1L<<13);
|
||||
static const uint64_t SegIsReduced = (1L<<14);
|
||||
static const uint64_t SegDrag = (1L<<15);
|
||||
static const uint64_t SegLayerChange = (1L<<16);
|
||||
static const uint64_t SegSourceTerminal = (1L<<17); // Replace Terminal.
|
||||
static const uint64_t SegTargetTerminal = (1L<<18); // Replace Terminal.
|
||||
static const uint64_t SegStrongTerminal = SegSourceTerminal|SegTargetTerminal;
|
||||
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);
|
||||
static const uint64_t SegWeakTerminal1 = (1L<<19); // Replace TopologicalEnd.
|
||||
static const uint64_t SegWeakTerminal2 = (1L<<20); // Replace TopologicalEnd.
|
||||
static const uint64_t SegNotSourceAligned = (1L<<21);
|
||||
static const uint64_t SegNotTargetAligned = (1L<<22);
|
||||
static const uint64_t SegUnbound = (1L<<23);
|
||||
static const uint64_t SegHalfSlackened = (1L<<24);
|
||||
static const uint64_t SegSlackened = (1L<<25);
|
||||
static const uint64_t SegAxisSet = (1L<<26);
|
||||
static const uint64_t SegInvalidated = (1L<<27);
|
||||
static const uint64_t SegInvalidatedSource = (1L<<28);
|
||||
static const uint64_t SegInvalidatedTarget = (1L<<29);
|
||||
static const uint64_t SegInvalidatedLayer = (1L<<30);
|
||||
static const uint64_t SegCreated = (1L<<31);
|
||||
static const uint64_t SegUserDefined = (1L<<32);
|
||||
static const uint64_t SegAnalog = (1L<<33);
|
||||
static const uint64_t SegWide = (1L<<34);
|
||||
// Masks.
|
||||
static const uint64_t SegWeakTerminal = SegStrongTerminal|SegWeakTerminal1|SegWeakTerminal2;
|
||||
static const uint64_t SegNotAligned = SegNotSourceAligned|SegNotTargetAligned;
|
||||
|
@ -133,6 +135,9 @@ namespace Anabatic {
|
|||
public:
|
||||
static void setAnalogMode ( bool );
|
||||
static bool getAnalogMode ();
|
||||
inline static DbU::Unit getViaToTopCap ( size_t depth );
|
||||
inline static DbU::Unit getViaToBottomCap ( size_t depth );
|
||||
inline static DbU::Unit getViaToSameCap ( size_t depth );
|
||||
static AutoSegment* create ( AutoContact* source
|
||||
, AutoContact* target
|
||||
, Segment* hurricaneSegment
|
||||
|
@ -179,6 +184,7 @@ namespace Anabatic {
|
|||
inline bool isLongLocal () const;
|
||||
inline bool isLocal () const;
|
||||
inline bool isFixed () const;
|
||||
inline bool isFixedAxis () const;
|
||||
inline bool isBipoint () const;
|
||||
inline bool isWeakTerminal () const;
|
||||
inline bool isWeakTerminal1 () const;
|
||||
|
@ -237,8 +243,12 @@ namespace Anabatic {
|
|||
inline unsigned int getDepth () const;
|
||||
inline DbU::Unit getPitch () const;
|
||||
DbU::Unit getPPitch () const;
|
||||
#if DISABLED
|
||||
DbU::Unit getExtensionCap () const;
|
||||
#endif
|
||||
DbU::Unit getExtensionCap ( Flags ) const;
|
||||
inline DbU::Unit getAxis () const;
|
||||
void getEndAxes ( DbU::Unit& sourceAxis, DbU::Unit& targetAxis ) const;
|
||||
virtual DbU::Unit getSourceU () const = 0;
|
||||
virtual DbU::Unit getTargetU () const = 0;
|
||||
virtual DbU::Unit getDuSource () const = 0;
|
||||
|
@ -348,6 +358,8 @@ namespace Anabatic {
|
|||
static size_t _allocateds;
|
||||
static size_t _globalsCount;
|
||||
static bool _analogMode;
|
||||
static bool _initialized;
|
||||
static vector< array<DbU::Unit*,3> > _extensionCaps;
|
||||
// Internal: Attributes.
|
||||
const unsigned long _id;
|
||||
GCell* _gcell;
|
||||
|
@ -370,6 +382,7 @@ namespace Anabatic {
|
|||
static void _preCreate ( AutoContact* source, AutoContact* target );
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
static void _initialize ();
|
||||
private:
|
||||
AutoSegment ( const AutoSegment& );
|
||||
AutoSegment& operator= ( const AutoSegment& );
|
||||
|
@ -391,8 +404,13 @@ namespace Anabatic {
|
|||
struct CompareByDepthAxis : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
struct CompareBySourceU : public binary_function<AutoSegment*,AutoSegment*,bool> {
|
||||
bool operator() ( AutoSegment* lhs, AutoSegment* rhs ) const;
|
||||
};
|
||||
public:
|
||||
typedef std::set<AutoSegment*,CompareByDepthLength> DepthLengthSet;
|
||||
typedef std::set<AutoSegment*,CompareId> IdSet;
|
||||
|
||||
// Static Utilities.
|
||||
public:
|
||||
|
@ -431,6 +449,9 @@ namespace Anabatic {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline DbU::Unit AutoSegment::getViaToTopCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][0]) : 0; }
|
||||
inline DbU::Unit AutoSegment::getViaToBottomCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][1]) : 0; }
|
||||
inline DbU::Unit AutoSegment::getViaToSameCap ( size_t depth ) { return (depth < _extensionCaps.size()) ? *(_extensionCaps[depth][2]) : 0; }
|
||||
inline unsigned long AutoSegment::getId () const { return _id; }
|
||||
inline Cell* AutoSegment::getCell () const { return base()->getCell(); }
|
||||
inline Net* AutoSegment::getNet () const { return base()->getNet(); }
|
||||
|
@ -471,6 +492,7 @@ namespace Anabatic {
|
|||
inline bool AutoSegment::isHorizontal () const { return _flags & SegHorizontal; }
|
||||
inline bool AutoSegment::isVertical () const { return not (_flags & SegHorizontal); }
|
||||
inline bool AutoSegment::isFixed () const { return _flags & SegFixed; }
|
||||
inline bool AutoSegment::isFixedAxis () const { return _flags & SegFixedAxis; }
|
||||
inline bool AutoSegment::isGlobal () const { return _flags & SegGlobal; }
|
||||
inline bool AutoSegment::isWeakGlobal () const { return _flags & SegWeakGlobal; }
|
||||
inline bool AutoSegment::isLongLocal () const { return _flags & SegLongLocal; }
|
||||
|
@ -532,7 +554,6 @@ namespace Anabatic {
|
|||
_parent = parent;
|
||||
}
|
||||
|
||||
|
||||
inline bool AutoSegment::CompareId::operator() ( const AutoSegment* lhs, const AutoSegment* rhs ) const
|
||||
{ return lhs->getId() < rhs->getId(); }
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ parametersTable = \
|
|||
routingGaugesTable = {}
|
||||
|
||||
routingGaugesTable['gscl45'] = \
|
||||
( ( 'metal1' , ( Gauge.Horizontal, Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.065, 7 ) )
|
||||
( ( 'symbolic', False )
|
||||
, ( 'metal1' , ( Gauge.Horizontal, Gauge.PinOnly, 0, 0.0, 0, 0.190, 0.065, 0.065, 7 ) )
|
||||
, ( 'metal2' , ( Gauge.Vertical , Gauge.Default, 1, 0.0, 0, 0.190, 0.070, 0.070, 8 ) )
|
||||
, ( 'metal3' , ( Gauge.Horizontal, Gauge.Default, 2, 0.0, 0, 0.190, 0.070, 0.070, 8 ) )
|
||||
, ( 'metal4' , ( Gauge.Vertical , Gauge.Default, 3, 0.0, 0, 0.285, 0.140, 0.140, 8 ) )
|
||||
|
|
|
@ -33,7 +33,18 @@ technoConfig = { 'name' : 'freepdk_45'
|
|||
# must be expressed in microns.
|
||||
|
||||
layersExtensionsTable = \
|
||||
( ('NWELL.nWell.extention.cap' , 0.0)
|
||||
( ('metal1.minimalSpacing' , 0.065)
|
||||
, ('metal2.minimalSpacing' , 0.075)
|
||||
, ('metal3.minimalSpacing' , 0.07 )
|
||||
, ('metal4.minimalSpacing' , 0.14 )
|
||||
, ('metal5.minimalSpacing' , 0.14 )
|
||||
, ('metal6.minimalSpacing' , 0.14 )
|
||||
, ('metal7.minimalSpacing' , 0.4 )
|
||||
, ('metal8.minimalSpacing' , 0.4 )
|
||||
, ('metal9.minimalSpacing' , 0.8 )
|
||||
, ('metal10.minimalSpacing' , 0.8 )
|
||||
|
||||
, ('NWELL.nWell.extention.cap' , 0.0)
|
||||
, ('PWELL.pWell.extention.cap' , 0.0)
|
||||
|
||||
, ('NTIE.minimum.width' , 3.0)
|
||||
|
@ -166,13 +177,15 @@ layersExtensionsTable = \
|
|||
|
||||
# VIAs (i.e. Metal <--> Metal) (real).
|
||||
, ('via12.minimum.side' , 0.065)
|
||||
, ('via12.metal1.enclosure' , 0.0 )
|
||||
, ('via12.metal2.enclosure' , 0.025)
|
||||
# This is the rule as defined in LEF, but seems wrong to me.
|
||||
#, ('via12.metal1.enclosure' , (0.035 , 0.0 ) )
|
||||
, ('via12.metal1.enclosure' , (0.0 , 0.035) )
|
||||
, ('via12.metal2.enclosure' , (0.0025, 0.035) )
|
||||
, ('via23.minimum.side' , 0.070)
|
||||
, ('via23.metal2.enclosure' , 0.0 )
|
||||
, ('via23.metal3.enclosure' , 0.035)
|
||||
, ('via23.metal2.enclosure' , (0.0 , 0.035) )
|
||||
, ('via23.metal3.enclosure' , (0.035 , 0.0 ) )
|
||||
, ('via34.minimum.side' , 0.070)
|
||||
, ('via34.metal3.enclosure' , 0.0 )
|
||||
, ('via34.metal3.enclosure' , (0.035, 0.0 ) )
|
||||
, ('via34.metal4.enclosure' , 0.035)
|
||||
, ('via45.minimum.side' , 0.140)
|
||||
, ('via45.metal4.enclosure' , 0.0 )
|
||||
|
|
|
@ -88,11 +88,11 @@ layersExtensionsTable = \
|
|||
# Routing Layers.
|
||||
, ('METAL1.minimum.width' , 1.0)
|
||||
, ('METAL1.metal1.extention.cap' , 0.5)
|
||||
, ('METAL2.minimum.width' , 1.0)
|
||||
, ('METAL2.minimum.width' , 2.0)
|
||||
, ('METAL2.metal2.extention.cap' , 1.0)
|
||||
, ('METAL3.minimum.width' , 1.0)
|
||||
, ('METAL3.minimum.width' , 2.0)
|
||||
, ('METAL3.metal3.extention.cap' , 1.0)
|
||||
, ('METAL4.minimum.width' , 1.0)
|
||||
, ('METAL4.minimum.width' , 2.0)
|
||||
, ('METAL4.metal4.extention.cap' , 1.0)
|
||||
, ('METAL5.minimum.width' , 2.0)
|
||||
, ('METAL5.metal5.extention.cap' , 1.0)
|
||||
|
|
|
@ -151,6 +151,11 @@ def loadRoutingGaugesTable ( routingGaugesTable, fromFile ):
|
|||
,'Must have exactly two fields ("METAL_LAYER", (parameters_list)).'
|
||||
,str(entry)
|
||||
])
|
||||
|
||||
if entry[0] == 'symbolic':
|
||||
gauge.setSymbolic( entry[1] )
|
||||
continue
|
||||
|
||||
if len(entry[1]) != 9:
|
||||
raise ErrorMessage(1,['Malformed entry in <routingGaugesTable[%s]>.' % gaugeName
|
||||
,'Parameters list must have exactly nine fields:'
|
||||
|
|
|
@ -216,36 +216,59 @@ def loadLayersExtensions ( layersExtensionsTable, confFile ):
|
|||
,'Must contains exactly two fields: ( rule_path, value ).'
|
||||
,str(rule)
|
||||
])
|
||||
if not isinstance(rule[1],int) and not isinstance(rule[1],float):
|
||||
if not isinstance(rule[1],int) \
|
||||
and not isinstance(rule[1],float) \
|
||||
and not isinstance(rule[1],tuple):
|
||||
raise ErrorMessage(1,['Invalid entry in <layersExtensionsTable>.'
|
||||
,'Rule value must be of integer or float type.'
|
||||
,'Rule value must be of integer, float, or pair a of those type.'
|
||||
,str(rule)
|
||||
])
|
||||
|
||||
elements = rule[0].split('.')
|
||||
if len(elements) < 3:
|
||||
if len(elements) == 2:
|
||||
ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Real|LayersLUT.MissingError )
|
||||
subLayer = None
|
||||
elif len(elements) == 3 or len(elements) == 4:
|
||||
ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Composite|LayersLUT.MissingError )
|
||||
subLayer = layersLUT.lookup( elements[1], LayersLUT.Real )
|
||||
else:
|
||||
raise ErrorMessage(1,['Invalid entry in <layersExtensionsTable>.'
|
||||
,'Rule name must contains at least three components: \"LAYER.category.dimension\".'
|
||||
,'Rule name must contains two or three components:'
|
||||
,' * \"COMP_LAYER.category.dimension\".'
|
||||
,' * \"REAL_LAYER.dimension\".'
|
||||
,str(rule)
|
||||
])
|
||||
|
||||
ruleLayer = layersLUT.lookup( elements[0], LayersLUT.Composite|LayersLUT.MissingError )
|
||||
subLayer = layersLUT.lookup( elements[1], LayersLUT.Real )
|
||||
|
||||
if elements[0].startswith('via'): value = toDbU(rule[1])
|
||||
else: value = DbU.fromLambda(rule[1])
|
||||
if elements[0].startswith('via') or elements[0].startswith('metal'):
|
||||
if isinstance(rule[1],tuple):
|
||||
value = ( toDbU(rule[1][0]), toDbU(rule[1][1]) )
|
||||
else:
|
||||
value = toDbU(rule[1])
|
||||
else:
|
||||
if isinstance(rule[1],tuple):
|
||||
value = ( DbU.fromLambda(rule[1][0]), DbU.fromLambda(rule[1][1]) )
|
||||
else:
|
||||
value = DbU.fromLambda(rule[1])
|
||||
|
||||
if subLayer: ruleTag = string.join(elements[2:],'.')
|
||||
else: ruleTag = string.join(elements[1:],'.')
|
||||
|
||||
if ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value )
|
||||
if ruleTag == 'minimalSpacing': ruleLayer.setMinimalSpacing( value )
|
||||
elif ruleTag == 'extention.cap': ruleLayer.setExtentionCap ( subLayer, value )
|
||||
elif ruleTag == 'extention.width': ruleLayer.setExtentionWidth( subLayer, value )
|
||||
elif ruleTag == 'enclosure': ruleLayer.setEnclosure ( subLayer, value )
|
||||
elif ruleTag == 'minimum.width': ruleLayer.setMinimalSize ( value )
|
||||
elif ruleTag == 'minimum.side': ruleLayer.setMinimalSize ( value )
|
||||
elif ruleTag == 'enclosure':
|
||||
if isinstance(value,tuple):
|
||||
ruleLayer.setEnclosure( subLayer, value[0], Layer.EnclosureH )
|
||||
ruleLayer.setEnclosure( subLayer, value[1], Layer.EnclosureV )
|
||||
else:
|
||||
ruleLayer.setEnclosure( subLayer, value, Layer.EnclosureH|Layer.EnclosureV )
|
||||
else:
|
||||
raise ErrorMessage(1,['Invalid entry in <layersExtensionsTable>.'
|
||||
,'Unknown rule kind: \".%s\", should be any of:' % ruleTag
|
||||
,' * "RULE_HEAD.minimalSpacing"'
|
||||
,' * "RULE_HEAD.extention.cap"'
|
||||
,' * "RULE_HEAD.extention.width"'
|
||||
,' * "RULE_HEAD.enclosure"'
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace CRL {
|
|||
, _layerGauges()
|
||||
, _viaLayers ()
|
||||
, _technology (DataBase::getDB()->getTechnology())
|
||||
, _isSymbolic (true)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -68,6 +69,7 @@ namespace CRL {
|
|||
, _layerGauges()
|
||||
, _viaLayers ()
|
||||
, _technology (gauge._technology)
|
||||
, _isSymbolic (gauge._isSymbolic)
|
||||
{
|
||||
// Make a deep copy of the map.
|
||||
for ( size_t i=0 ; i<gauge._layerGauges.size() ; i++ )
|
||||
|
@ -285,6 +287,7 @@ namespace CRL {
|
|||
|
||||
record->add ( getSlot("_name" , _name ) );
|
||||
record->add ( getSlot("_gauges" ,&_layerGauges) );
|
||||
record->add ( getSlot("_isSymbolic", _isSymbolic ) );
|
||||
return ( record );
|
||||
}
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ namespace CRL {
|
|||
switch ( ruleType ) {
|
||||
case ExtentionCap: ruleLayer->setExtentionCap (basicLayer,DbU::lambda(doubleValue)); break;
|
||||
case ExtentionWidth: ruleLayer->setExtentionWidth(basicLayer,DbU::lambda(doubleValue)); break;
|
||||
case Enclosure: ruleLayer->setEnclosure (basicLayer,DbU::lambda(doubleValue)); break;
|
||||
case Enclosure: ruleLayer->setEnclosure (basicLayer,DbU::lambda(doubleValue),Layer::EnclosureH|Layer::EnclosureV); break;
|
||||
case MinimumWidth: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break;
|
||||
case MinimumSide: ruleLayer->setMinimalSize (DbU::lambda(doubleValue)); break;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace CRL {
|
|||
static RoutingGauge* create ( const char* name );
|
||||
virtual void destroy ();
|
||||
// Predicates.
|
||||
inline bool isSymbolic () const;
|
||||
inline bool isTwoMetals () const;
|
||||
inline bool isHV () const;
|
||||
inline bool isVH () const;
|
||||
|
@ -85,6 +86,7 @@ namespace CRL {
|
|||
// Methods.
|
||||
void addLayerGauge ( RoutingLayerGauge* layerGauge );
|
||||
void checkConnexity () const;
|
||||
inline void setSymbolic ( bool );
|
||||
// Hurricane Managment.
|
||||
void toJson ( JsonWriter* ) const;
|
||||
virtual Record* _getRecord ( Record* record=NULL ) const;
|
||||
|
@ -97,6 +99,7 @@ namespace CRL {
|
|||
vector<RoutingLayerGauge*> _layerGauges;
|
||||
vector<Layer*> _viaLayers;
|
||||
Technology* _technology;
|
||||
bool _isSymbolic;
|
||||
|
||||
// Internal - Constructors & Destructors.
|
||||
RoutingGauge ( const char* name );
|
||||
|
@ -107,6 +110,7 @@ namespace CRL {
|
|||
};
|
||||
|
||||
|
||||
inline bool RoutingGauge::isSymbolic () const { return _isSymbolic; }
|
||||
inline bool RoutingGauge::isTwoMetals () const { return (getDepth() < 3); }
|
||||
inline bool RoutingGauge::isHV () const { return not isTwoMetals() and (getLayerGauge(1)->isHorizontal()); }
|
||||
inline bool RoutingGauge::isVH () const { return not isTwoMetals() and (getLayerGauge(1)->isVertical()); }
|
||||
|
@ -121,6 +125,7 @@ namespace CRL {
|
|||
inline DbU::Unit RoutingGauge::getLayerOffset ( size_t depth ) const { return getLayerGauge(depth)->getOffset(); }
|
||||
inline DbU::Unit RoutingGauge::getLayerWireWidth ( size_t depth ) const { return getLayerGauge(depth)->getWireWidth(); }
|
||||
inline DbU::Unit RoutingGauge::getViaWidth ( size_t depth ) const { return getLayerGauge(depth)->getViaWidth(); }
|
||||
inline void RoutingGauge::setSymbolic ( bool state ) { _isSymbolic=state; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
|
|
@ -358,6 +358,8 @@ extern "C" {
|
|||
// Standard Attributes.
|
||||
GetNameMethod(RoutingGauge,rg)
|
||||
accessorVectorFromVoid(getLayerGauges,PyRoutingGauge,RoutingGauge,RoutingLayerGauge)
|
||||
DirectGetBoolAttribute(PyRoutingGauge_isSymbolic ,isSymbolic ,PyRoutingGauge,RoutingGauge)
|
||||
DirectSetBoolAttribute(PyRoutingGauge_setSymbolic,setSymbolic,PyRoutingGauge,RoutingGauge)
|
||||
|
||||
|
||||
// Standart Destroy (Attribute).
|
||||
|
@ -366,6 +368,8 @@ extern "C" {
|
|||
PyMethodDef PyRoutingGauge_Methods[] =
|
||||
{ { "create" , (PyCFunction)PyRoutingGauge_create , METH_VARARGS|METH_STATIC
|
||||
, "Create a new RoutingGauge." }
|
||||
, { "isSymbolic" , (PyCFunction)PyRoutingGauge_isSymbolic , METH_NOARGS
|
||||
, "The RoutingGauge is for symbolic technology." }
|
||||
, { "getName" , (PyCFunction)PyRoutingGauge_getName , METH_NOARGS
|
||||
, "Return the maximum depth of the RoutingGauge." }
|
||||
, { "getTechnology" , (PyCFunction)PyRoutingGauge_getTechnology , METH_NOARGS
|
||||
|
@ -392,6 +396,8 @@ extern "C" {
|
|||
, "Return the list of RoutingLayerGauge." }
|
||||
, { "addLayerGauge" , (PyCFunction)PyRoutingGauge_addLayerGauge , METH_VARARGS
|
||||
, "Adds a new RoutingLayerGauge to the RoutingGauge." }
|
||||
, { "setSymbolic" , (PyCFunction)PyRoutingGauge_setSymbolic , METH_VARARGS
|
||||
, "Set the symbolic technology state." }
|
||||
//, { "destroy" , (PyCFunction)PyRoutingGauge_destroy , METH_VARARGS
|
||||
// , "Destroy the associated hurricane object. The python object remains." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
|
|
|
@ -200,19 +200,21 @@ Point Contact::getPosition() const
|
|||
Box Contact::getBoundingBox() const
|
||||
// ********************************
|
||||
{
|
||||
DbU::Unit size = getLayer()->getEnclosure();
|
||||
DbU::Unit enclosureH = getLayer()->getEnclosure( Layer::EnclosureH );
|
||||
DbU::Unit enclosureV = getLayer()->getEnclosure( Layer::EnclosureV );
|
||||
|
||||
return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size);
|
||||
return Box(getPosition()).inflate(getHalfWidth() + enclosureH, getHalfHeight() + enclosureV);
|
||||
}
|
||||
|
||||
Box Contact::getBoundingBox(const BasicLayer* basicLayer) const
|
||||
// ******************************************************
|
||||
{
|
||||
if (!_layer->contains(basicLayer)) return Box();
|
||||
if (not _layer->contains(basicLayer)) return Box();
|
||||
|
||||
DbU::Unit size = getLayer()->getEnclosure(basicLayer);
|
||||
DbU::Unit enclosureH = getLayer()->getEnclosure( basicLayer, Layer::EnclosureH );
|
||||
DbU::Unit enclosureV = getLayer()->getEnclosure( basicLayer, Layer::EnclosureV );
|
||||
|
||||
return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size);
|
||||
return Box(getPosition()).inflate(getHalfWidth() + enclosureH, getHalfHeight() + enclosureV );
|
||||
}
|
||||
|
||||
Component* Contact::getAnchor() const
|
||||
|
|
|
@ -69,39 +69,37 @@ namespace Hurricane {
|
|||
,_enclosures()
|
||||
,_maximalEnclosure(0)
|
||||
{
|
||||
if ( !metalLayer ) throw Error ( nullLayer, getString(name).c_str(), "Metal" );
|
||||
if ( !cutLayer ) throw Error ( nullLayer, getString(name).c_str(), "Cut" );
|
||||
if ( !activeLayer ) throw Error ( nullLayer, getString(name).c_str(), "Active" );
|
||||
if ( !diffusionLayer ) throw Error ( nullLayer, getString(name).c_str(), "Diffusion" );
|
||||
if (not metalLayer ) throw Error ( nullLayer, getString(name).c_str(), "Metal" );
|
||||
if (not cutLayer ) throw Error ( nullLayer, getString(name).c_str(), "Cut" );
|
||||
if (not activeLayer ) throw Error ( nullLayer, getString(name).c_str(), "Active" );
|
||||
if (not diffusionLayer) throw Error ( nullLayer, getString(name).c_str(), "Diffusion" );
|
||||
|
||||
_basicLayers.reserve ( 5 );
|
||||
_enclosures .reserve ( 5 );
|
||||
_basicLayers.reserve( 5 );
|
||||
_enclosures .reserve( 5 );
|
||||
|
||||
// Have to check wich one is top layer & cutLayer of type cut.
|
||||
_basicLayers.push_back ( metalLayer );
|
||||
_basicLayers.push_back ( cutLayer );
|
||||
_basicLayers.push_back ( activeLayer );
|
||||
_basicLayers.push_back ( diffusionLayer );
|
||||
_basicLayers.push_back( metalLayer );
|
||||
_basicLayers.push_back( cutLayer );
|
||||
_basicLayers.push_back( activeLayer );
|
||||
_basicLayers.push_back( diffusionLayer );
|
||||
|
||||
for ( size_t i=0 ; i<4 ; i++ ) {
|
||||
_enclosures.push_back ( 0 );
|
||||
}
|
||||
for ( size_t i=0 ; i<4 ; i++ ) _enclosures.push_back( make_pair(0,0) );
|
||||
|
||||
_setMask ( metalLayer ->getMask()
|
||||
| cutLayer ->getMask()
|
||||
| activeLayer ->getMask()
|
||||
| diffusionLayer->getMask() );
|
||||
_setExtractMask ( metalLayer ->getExtractMask()
|
||||
_setExtractMask( metalLayer ->getExtractMask()
|
||||
| cutLayer ->getExtractMask()
|
||||
| activeLayer ->getExtractMask()
|
||||
| diffusionLayer->getExtractMask() );
|
||||
|
||||
if ( wellLayer ) {
|
||||
_basicLayers.push_back ( wellLayer );
|
||||
_enclosures .push_back ( 0 );
|
||||
if (wellLayer) {
|
||||
_basicLayers.push_back( wellLayer );
|
||||
_enclosures .push_back( make_pair(0,0) );
|
||||
|
||||
_setMask ( getMask() | wellLayer->getMask() );
|
||||
_setExtractMask ( getMask() | wellLayer->getExtractMask() );
|
||||
_setExtractMask( getMask() | wellLayer->getExtractMask() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,37 +132,60 @@ namespace Hurricane {
|
|||
{ return getCollection(_basicLayers); }
|
||||
|
||||
|
||||
DbU::Unit ContactLayer::getEnclosure () const
|
||||
{ return _maximalEnclosure; }
|
||||
DbU::Unit ContactLayer::getEnclosure ( uint32_t flags ) const
|
||||
{
|
||||
if (flags & (Layer::EnclosureH|Layer::EnclosureV)) return _maximalEnclosure;
|
||||
|
||||
DbU::Unit enclosure = 0;
|
||||
if (flags & Layer::EnclosureH) {
|
||||
for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.first );
|
||||
}
|
||||
if (flags & Layer::EnclosureV) {
|
||||
for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.second );
|
||||
}
|
||||
|
||||
return enclosure;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit ContactLayer::getEnclosure ( const BasicLayer* layer ) const
|
||||
DbU::Unit ContactLayer::getEnclosure ( const BasicLayer* layer, uint32_t flags ) const
|
||||
{
|
||||
for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) {
|
||||
if ( _basicLayers[i] == layer )
|
||||
return _enclosures[i];
|
||||
if ( _basicLayers[i] == layer ) {
|
||||
|
||||
if (flags & Layer::EnclosureH) {
|
||||
if (flags & Layer::EnclosureV) return std::max( _enclosures[i].first, _enclosures[i].second );
|
||||
return _enclosures[i].first;
|
||||
}
|
||||
if (flags & Layer::EnclosureV) return _enclosures[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ContactLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure )
|
||||
void ContactLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags )
|
||||
{
|
||||
_maximalEnclosure = 0;
|
||||
for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) {
|
||||
if ( _basicLayers[i] == layer ) {
|
||||
_enclosures[i] = enclosure;
|
||||
_maximalEnclosure = max ( _maximalEnclosure, enclosure );
|
||||
if (flags & Layer::EnclosureH) _enclosures[i].first = enclosure;
|
||||
if (flags & Layer::EnclosureV) _enclosures[i].second = enclosure;
|
||||
}
|
||||
_maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].first );
|
||||
_maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].second );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ContactLayer::_onDbuChange ( float scale )
|
||||
{
|
||||
Layer::_onDbuChange ( scale );
|
||||
for ( size_t i=0 ; i<_enclosures.size() ; i++ )
|
||||
_enclosures[i] = (DbU::Unit)( (float)_enclosures[i] * scale );
|
||||
Layer::_onDbuChange( scale );
|
||||
for ( size_t i=0 ; i<_enclosures.size() ; i++ ) {
|
||||
_enclosures[i].first = (DbU::Unit)( (float)_enclosures[i].first * scale );
|
||||
_enclosures[i].second = (DbU::Unit)( (float)_enclosures[i].second * scale );
|
||||
}
|
||||
_maximalEnclosure = (DbU::Unit)( (float)_maximalEnclosure * scale );
|
||||
}
|
||||
|
||||
|
@ -202,11 +223,16 @@ namespace Hurricane {
|
|||
if (_basicLayers.size() == 5) jsonWrite( w, "_well", _basicLayers[4]->getName() );
|
||||
else jsonWrite( w, "_well", "no_well_layer" );
|
||||
|
||||
jsonWrite( w, "_enclosure.metal" , _enclosures[0] );
|
||||
jsonWrite( w, "_enclosure.cut" , _enclosures[1] );
|
||||
jsonWrite( w, "_enclosure.active" , _enclosures[2] );
|
||||
jsonWrite( w, "_enclosure.diffusion", _enclosures[3] );
|
||||
jsonWrite( w, "_enclosure.well" , (_basicLayers.size() == 5) ? _enclosures[4] : 0 );
|
||||
jsonWrite( w, "_enclosureH.metal" , _enclosures[0].first );
|
||||
jsonWrite( w, "_enclosureV.metal" , _enclosures[0].second );
|
||||
jsonWrite( w, "_enclosureH.cut" , _enclosures[1].first );
|
||||
jsonWrite( w, "_enclosureV.cut" , _enclosures[1].second );
|
||||
jsonWrite( w, "_enclosureH.active" , _enclosures[2].first );
|
||||
jsonWrite( w, "_enclosureV.active" , _enclosures[2].second );
|
||||
jsonWrite( w, "_enclosureH.diffusion", _enclosures[3].first );
|
||||
jsonWrite( w, "_enclosureV.diffusion", _enclosures[3].second );
|
||||
jsonWrite( w, "_enclosureH.well" , (_basicLayers.size() == 5) ? _enclosures[4].first : 0 );
|
||||
jsonWrite( w, "_enclosureV.well" , (_basicLayers.size() == 5) ? _enclosures[4].second : 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -232,11 +258,16 @@ namespace Hurricane {
|
|||
add( "_active" , typeid(string) );
|
||||
add( "_diffusion" , typeid(string) );
|
||||
add( "_well" , typeid(string) );
|
||||
add( "_enclosure.metal" , typeid(int64_t) );
|
||||
add( "_enclosure.cut" , typeid(int64_t) );
|
||||
add( "_enclosure.active" , typeid(int64_t) );
|
||||
add( "_enclosure.diffusion", typeid(int64_t) );
|
||||
add( "_enclosure.well" , typeid(int64_t) );
|
||||
add( "_enclosureH.metal" , typeid(int64_t) );
|
||||
add( "_enclosureV.metal" , typeid(int64_t) );
|
||||
add( "_enclosureH.cut" , typeid(int64_t) );
|
||||
add( "_enclosureV.cut" , typeid(int64_t) );
|
||||
add( "_enclosureH.active" , typeid(int64_t) );
|
||||
add( "_enclosureV.active" , typeid(int64_t) );
|
||||
add( "_enclosureH.diffusion", typeid(int64_t) );
|
||||
add( "_enclosureV.diffusion", typeid(int64_t) );
|
||||
add( "_enclosureH.well" , typeid(int64_t) );
|
||||
add( "_enclosureV.well" , typeid(int64_t) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -273,11 +304,16 @@ namespace Hurricane {
|
|||
BasicLayer* active = techno->getBasicLayer( get<string>(stack,"_active" ) );
|
||||
BasicLayer* diffusion = techno->getBasicLayer( get<string>(stack,"_diffusion") );
|
||||
BasicLayer* well = techno->getBasicLayer( get<string>(stack,"_well" ) );
|
||||
DbU::Unit metalEncl = get<int64_t>( stack, "_enclosure.metal" );
|
||||
DbU::Unit cutEncl = get<int64_t>( stack, "_enclosure.cut" );
|
||||
DbU::Unit activeEncl = get<int64_t>( stack, "_enclosure.active" );
|
||||
DbU::Unit diffusionEncl = get<int64_t>( stack, "_enclosure.diffusion" );
|
||||
DbU::Unit wellEncl = get<int64_t>( stack, "_enclosure.well" );
|
||||
DbU::Unit metalEnclH = get<int64_t>( stack, "_enclosureH.metal" );
|
||||
DbU::Unit metalEnclV = get<int64_t>( stack, "_enclosureV.metal" );
|
||||
DbU::Unit cutEnclH = get<int64_t>( stack, "_enclosureH.cut" );
|
||||
DbU::Unit cutEnclV = get<int64_t>( stack, "_enclosureV.cut" );
|
||||
DbU::Unit activeEnclH = get<int64_t>( stack, "_enclosureH.active" );
|
||||
DbU::Unit activeEnclV = get<int64_t>( stack, "_enclosureV.active" );
|
||||
DbU::Unit diffusionEnclH = get<int64_t>( stack, "_enclosureH.diffusion" );
|
||||
DbU::Unit diffusionEnclV = get<int64_t>( stack, "_enclosureV.diffusion" );
|
||||
DbU::Unit wellEnclH = get<int64_t>( stack, "_enclosureH.well" );
|
||||
DbU::Unit wellEnclV = get<int64_t>( stack, "_enclosureV.well" );
|
||||
|
||||
Layer::Mask mask = Layer::Mask::fromString( smask );
|
||||
|
||||
|
@ -292,11 +328,18 @@ namespace Hurricane {
|
|||
, well
|
||||
);
|
||||
layer->setSymbolic ( isSymbolic );
|
||||
layer->setEnclosure( metal , metalEncl );
|
||||
layer->setEnclosure( cut , cutEncl );
|
||||
layer->setEnclosure( active , activeEncl );
|
||||
layer->setEnclosure( diffusion, diffusionEncl );
|
||||
if (well) layer->setEnclosure( well, wellEncl );
|
||||
layer->setEnclosure( metal , metalEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( metal , metalEnclV , Layer::EnclosureV );
|
||||
layer->setEnclosure( cut , cutEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( cut , cutEnclV , Layer::EnclosureV );
|
||||
layer->setEnclosure( active , activeEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( active , activeEnclV , Layer::EnclosureV );
|
||||
layer->setEnclosure( diffusion, diffusionEnclH, Layer::EnclosureH );
|
||||
layer->setEnclosure( diffusion, diffusionEnclV, Layer::EnclosureV );
|
||||
if (well) {
|
||||
layer->setEnclosure( well, wellEnclH, Layer::EnclosureH );
|
||||
layer->setEnclosure( well, wellEnclV, Layer::EnclosureV );
|
||||
}
|
||||
|
||||
if (layer->getMask() != mask) {
|
||||
cerr << Error( "JsonContactLayer::toData(): Layer mask re-creation discrepency on \"%s\":\n"
|
||||
|
|
|
@ -327,7 +327,7 @@ namespace Hurricane {
|
|||
case Min: os << "MIN:"; break;
|
||||
case Max: os << "MAX:"; break;
|
||||
default:
|
||||
os << setprecision(3) << toPhysical(u,_stringModeUnitPower);
|
||||
os << setprecision(4) << toPhysical(u,_stringModeUnitPower);
|
||||
}
|
||||
} else {
|
||||
if (_stringMode != Db)
|
||||
|
|
|
@ -100,7 +100,15 @@ namespace Hurricane {
|
|||
{ return _technology->getCutBelow(this,useSymbolic); }
|
||||
|
||||
|
||||
DbU::Unit Layer::getEnclosure () const
|
||||
DbU::Unit Layer::getEnclosure ( uint32_t ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
DbU::Unit Layer::getTopEnclosure ( uint32_t ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
DbU::Unit Layer::getBottomEnclosure ( uint32_t ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
|
@ -112,15 +120,15 @@ namespace Hurricane {
|
|||
{ return 0; }
|
||||
|
||||
|
||||
DbU::Unit Layer::getEnclosure ( const BasicLayer* layer ) const
|
||||
DbU::Unit Layer::getEnclosure ( const BasicLayer*, uint32_t ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
DbU::Unit Layer::getExtentionCap ( const BasicLayer* layer ) const
|
||||
DbU::Unit Layer::getExtentionCap ( const BasicLayer* ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
DbU::Unit Layer::getExtentionWidth ( const BasicLayer* layer ) const
|
||||
DbU::Unit Layer::getExtentionWidth ( const BasicLayer* ) const
|
||||
{ return 0; }
|
||||
|
||||
|
||||
|
@ -164,7 +172,7 @@ namespace Hurricane {
|
|||
}
|
||||
|
||||
|
||||
void Layer::setEnclosure ( const BasicLayer* layer, DbU::Unit )
|
||||
void Layer::setEnclosure ( const BasicLayer*, DbU::Unit, uint32_t )
|
||||
{
|
||||
cerr << "[WARNING] Layer::setEnclosure() musn't be called on "
|
||||
<< _getTypeName() << ": dummy implementation." << endl;
|
||||
|
|
|
@ -312,15 +312,17 @@ namespace Hurricane {
|
|||
|
||||
Occurrence RoutingPad::getPlugOccurrence ()
|
||||
{
|
||||
if (dynamic_cast<Plug*>(_occurrence.getEntity()))
|
||||
return _occurrence;
|
||||
if (dynamic_cast<Plug*>(_occurrence.getEntity())) return _occurrence;
|
||||
|
||||
Component* component = static_cast<Component*>(_occurrence.getEntity());
|
||||
Net* net = component->getNet();
|
||||
Path path = _occurrence.getPath();
|
||||
|
||||
if ( path.isEmpty() )
|
||||
throw Error("Empty Path => not in an instance");
|
||||
if (path.isEmpty())
|
||||
throw Error( "RoutingPad::getPlugOccurrence(): Empty Path, *not* in an instance for\n"
|
||||
" %s"
|
||||
, getString(this).c_str()
|
||||
);
|
||||
|
||||
Instance* instance = path.getTailInstance();
|
||||
Plug* plug = instance->getPlug(net);
|
||||
|
|
|
@ -95,9 +95,9 @@ namespace Hurricane {
|
|||
| cutLayer ->getExtractMask()
|
||||
| topLayer ->getExtractMask() );
|
||||
|
||||
_enclosures.push_back ( 0 );
|
||||
_enclosures.push_back ( 0 );
|
||||
_enclosures.push_back ( 0 );
|
||||
_enclosures.push_back ( make_pair(0,0) );
|
||||
_enclosures.push_back ( make_pair(0,0) );
|
||||
_enclosures.push_back ( make_pair(0,0) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,40 +141,82 @@ namespace Hurricane {
|
|||
}
|
||||
|
||||
|
||||
DbU::Unit ViaLayer::getEnclosure () const
|
||||
DbU::Unit ViaLayer::getEnclosure ( uint32_t flags ) const
|
||||
{
|
||||
return _maximalEnclosure;
|
||||
if (flags & (Layer::EnclosureH|Layer::EnclosureV)) return _maximalEnclosure;
|
||||
|
||||
DbU::Unit enclosure = 0;
|
||||
if (flags & Layer::EnclosureH) {
|
||||
for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.first );
|
||||
}
|
||||
if (flags & Layer::EnclosureV) {
|
||||
for ( auto element : _enclosures ) enclosure = std::max( enclosure, element.second );
|
||||
}
|
||||
|
||||
return enclosure;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit ViaLayer::getEnclosure ( const BasicLayer* layer ) const
|
||||
DbU::Unit ViaLayer::getEnclosure ( const BasicLayer* layer, uint32_t flags ) const
|
||||
{
|
||||
for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) {
|
||||
if ( layer == _basicLayers[i] ) return _enclosures[i];
|
||||
if ( _basicLayers[i] == layer ) {
|
||||
|
||||
if (flags & Layer::EnclosureH) {
|
||||
if (flags & Layer::EnclosureV) return std::max( _enclosures[i].first, _enclosures[i].second );
|
||||
return _enclosures[i].first;
|
||||
}
|
||||
if (flags & Layer::EnclosureV) return _enclosures[i].second;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ViaLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure )
|
||||
DbU::Unit ViaLayer::getTopEnclosure ( uint32_t flags ) const
|
||||
{
|
||||
for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) {
|
||||
if ( layer == _basicLayers[i] ) {
|
||||
_enclosures[i] = enclosure;
|
||||
_maximalEnclosure = max ( _maximalEnclosure, enclosure );
|
||||
if (flags & Layer::EnclosureH) {
|
||||
if (flags & Layer::EnclosureV) return std::max( _enclosures[2].first, _enclosures[2].second );
|
||||
return _enclosures[2].first;
|
||||
}
|
||||
if (flags & Layer::EnclosureV) return _enclosures[2].second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit ViaLayer::getBottomEnclosure ( uint32_t flags ) const
|
||||
{
|
||||
if (flags & Layer::EnclosureH) {
|
||||
if (flags & Layer::EnclosureV) return std::max( _enclosures[0].first, _enclosures[0].second );
|
||||
return _enclosures[0].first;
|
||||
}
|
||||
if (flags & Layer::EnclosureV) return _enclosures[0].second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ViaLayer::setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags )
|
||||
{
|
||||
_maximalEnclosure = 0;
|
||||
for ( size_t i=0 ; i<_basicLayers.size() ; i++ ) {
|
||||
if ( _basicLayers[i] == layer ) {
|
||||
if (flags & Layer::EnclosureH) _enclosures[i].first = enclosure;
|
||||
if (flags & Layer::EnclosureV) _enclosures[i].second = enclosure;
|
||||
}
|
||||
_maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].first );
|
||||
_maximalEnclosure = std::max( _maximalEnclosure, _enclosures[i].second );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ViaLayer::_onDbuChange ( float scale )
|
||||
{
|
||||
Layer::_onDbuChange ( scale );
|
||||
|
||||
for ( size_t i=0 ; i<_enclosures.size() ; i++ )
|
||||
_enclosures[i] = (DbU::Unit)( (float)_enclosures[i] * scale );
|
||||
|
||||
Layer::_onDbuChange( scale );
|
||||
for ( size_t i=0 ; i<_enclosures.size() ; i++ ) {
|
||||
_enclosures[i].first = (DbU::Unit)( (float)_enclosures[i].first * scale );
|
||||
_enclosures[i].second = (DbU::Unit)( (float)_enclosures[i].second * scale );
|
||||
}
|
||||
_maximalEnclosure = (DbU::Unit)( (float)_maximalEnclosure * scale );
|
||||
}
|
||||
|
||||
|
@ -209,9 +251,12 @@ namespace Hurricane {
|
|||
jsonWrite( w, "_cut" , _basicLayers[1]->getName() );
|
||||
jsonWrite( w, "_top" , _basicLayers[2]->getName() );
|
||||
|
||||
jsonWrite( w, "_enclosure.bottom", _enclosures[0] );
|
||||
jsonWrite( w, "_enclosure.cut" , _enclosures[1] );
|
||||
jsonWrite( w, "_enclosure.top" , _enclosures[2] );
|
||||
jsonWrite( w, "_enclosureH.bottom", _enclosures[0].first );
|
||||
jsonWrite( w, "_enclosureV.bottom", _enclosures[0].second );
|
||||
jsonWrite( w, "_enclosureH.cut" , _enclosures[1].first );
|
||||
jsonWrite( w, "_enclosureV.cut" , _enclosures[1].second );
|
||||
jsonWrite( w, "_enclosureH.top" , _enclosures[2].first );
|
||||
jsonWrite( w, "_enclosureV.top" , _enclosures[2].second );
|
||||
}
|
||||
|
||||
|
||||
|
@ -235,9 +280,12 @@ namespace Hurricane {
|
|||
add( "_bottom" , typeid(string) );
|
||||
add( "_cut" , typeid(string) );
|
||||
add( "_top" , typeid(string) );
|
||||
add( "_enclosure.bottom", typeid(int64_t) );
|
||||
add( "_enclosure.cut" , typeid(int64_t) );
|
||||
add( "_enclosure.top" , typeid(int64_t) );
|
||||
add( "_enclosureH.bottom", typeid(int64_t) );
|
||||
add( "_enclosureV.bottom", typeid(int64_t) );
|
||||
add( "_enclosureH.cut" , typeid(int64_t) );
|
||||
add( "_enclosureV.cut" , typeid(int64_t) );
|
||||
add( "_enclosureH.top" , typeid(int64_t) );
|
||||
add( "_enclosureV.top" , typeid(int64_t) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,9 +320,12 @@ namespace Hurricane {
|
|||
BasicLayer* bottom = techno->getBasicLayer( get<string>(stack,"_bottom" ) );
|
||||
BasicLayer* cut = techno->getBasicLayer( get<string>(stack,"_cut" ) );
|
||||
BasicLayer* top = techno->getBasicLayer( get<string>(stack,"_top" ) );
|
||||
DbU::Unit bottomEncl = get<int64_t>( stack, "_enclosure.bottom" );
|
||||
DbU::Unit cutEncl = get<int64_t>( stack, "_enclosure.cut" );
|
||||
DbU::Unit topEncl = get<int64_t>( stack, "_enclosure.top" );
|
||||
DbU::Unit bottomEnclH = get<int64_t>( stack, "_enclosureH.bottom" );
|
||||
DbU::Unit bottomEnclV = get<int64_t>( stack, "_enclosureV.bottom" );
|
||||
DbU::Unit cutEnclH = get<int64_t>( stack, "_enclosureH.cut" );
|
||||
DbU::Unit cutEnclV = get<int64_t>( stack, "_enclosureV.cut" );
|
||||
DbU::Unit topEnclH = get<int64_t>( stack, "_enclosureH.top" );
|
||||
DbU::Unit topEnclV = get<int64_t>( stack, "_enclosureV.top" );
|
||||
|
||||
Layer::Mask mask = Layer::Mask::fromString( smask );
|
||||
|
||||
|
@ -287,9 +338,12 @@ namespace Hurricane {
|
|||
, top
|
||||
);
|
||||
layer->setSymbolic ( isSymbolic );
|
||||
layer->setEnclosure( bottom, bottomEncl );
|
||||
layer->setEnclosure( cut , cutEncl );
|
||||
layer->setEnclosure( top , topEncl );
|
||||
layer->setEnclosure( bottom, bottomEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( bottom, bottomEnclV , Layer::EnclosureV );
|
||||
layer->setEnclosure( cut , cutEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( cut , cutEnclV , Layer::EnclosureV );
|
||||
layer->setEnclosure( top , topEnclH , Layer::EnclosureH );
|
||||
layer->setEnclosure( top , topEnclV , Layer::EnclosureV );
|
||||
|
||||
if (layer->getMask() != mask) {
|
||||
cerr << Error( "JsonViaLayer::toData(): Layer mask re-creation discrepency on \"%s\":\n"
|
||||
|
|
|
@ -329,6 +329,45 @@ template<typename Data> inline Hurricane::Record* getRecord ( Data data )
|
|||
{ return NULL; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Inspector Support for : "[const] std::pair<T,U>&".
|
||||
|
||||
template<typename T, typename U>
|
||||
inline std::string getString ( const std::pair<T,U>& p )
|
||||
{
|
||||
return "const std::pair<T,U>";
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename U>
|
||||
inline Hurricane::Record* getRecord ( const std::pair<T,U>& p )
|
||||
{
|
||||
Hurricane::Record* record = NULL;
|
||||
record = new Hurricane::Record ( "const std::pair<T,U>" );
|
||||
record->add( getSlot<T>("first" , &p.first ) );
|
||||
record->add( getSlot<U>("second", &p.second) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename U>
|
||||
inline std::string getString ( std::pair<T,U>& p )
|
||||
{
|
||||
return "std::pair<T,U>";
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename U>
|
||||
inline Hurricane::Record* getRecord ( std::pair<T,U>& p )
|
||||
{
|
||||
Hurricane::Record* record = NULL;
|
||||
record = new Hurricane::Record ( "std::pair<T,U>" );
|
||||
record->add( getSlot<T>("first" , &p.first ) );
|
||||
record->add( getSlot<U>("second", &p.second) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Inspector Support for : "[const] std::array<Element>*".
|
||||
|
||||
|
|
|
@ -59,10 +59,10 @@ namespace Hurricane {
|
|||
);
|
||||
// Accessors.
|
||||
virtual BasicLayers getBasicLayers () const;
|
||||
virtual DbU::Unit getEnclosure () const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const;
|
||||
virtual DbU::Unit getEnclosure ( uint32_t flags ) const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const;
|
||||
// Updators.
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure );
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags );
|
||||
// Hurricane Managment.
|
||||
virtual void _toJson ( JsonWriter* ) const;
|
||||
virtual void _onDbuChange ( float scale );
|
||||
|
@ -73,7 +73,7 @@ namespace Hurricane {
|
|||
private:
|
||||
// Internal: Attributes
|
||||
vector<BasicLayer*> _basicLayers;
|
||||
vector<DbU::Unit> _enclosures;
|
||||
vector< pair<DbU::Unit,DbU::Unit> > _enclosures;
|
||||
DbU::Unit _maximalEnclosure;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -187,4 +187,43 @@ namespace Hurricane {
|
|||
// { w->key( key ); w->write( value ); }
|
||||
|
||||
|
||||
template<>
|
||||
inline std::string getString ( const std::pair<Hurricane::DbU::Unit,Hurricane::DbU::Unit>& p )
|
||||
{
|
||||
return "const std::pair<DbU::Unit,DbU::Unit>";
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline Hurricane::Record* getRecord ( const std::pair<Hurricane::DbU::Unit,Hurricane::DbU::Unit>& p )
|
||||
{
|
||||
Hurricane::Record* record = NULL;
|
||||
record = new Hurricane::Record ( "const std::pair<DbU::Unit,DbU::Unit>" );
|
||||
record->add( Hurricane::DbU::getValueSlot("first" , &p.first ) );
|
||||
record->add( Hurricane::DbU::getValueSlot("second", &p.second) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline std::string getString ( const std::array<Hurricane::DbU::Unit*,3>& a )
|
||||
{
|
||||
return "const array<DbU::Unit*,3>";
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
inline Hurricane::Record* getRecord ( const std::array<Hurricane::DbU::Unit*,3>& a )
|
||||
{
|
||||
Hurricane::Record* record = NULL;
|
||||
record = new Hurricane::Record ( "const array<DbU::Unit*,3>" );
|
||||
|
||||
for ( size_t i=0 ; i<a.size() ; ++i ) {
|
||||
std::string label = "[" + getString(i) + "] ";
|
||||
record->add( Hurricane::DbU::getValueSlot(label, a[i]) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
#endif // HURRICANE_DBU_H
|
||||
|
|
|
@ -63,7 +63,7 @@ class Interval {
|
|||
public: DbU::Unit& getVMin() {return _vMin;};
|
||||
public: DbU::Unit& getVMax() {return _vMax;};
|
||||
public: DbU::Unit getCenter() const {return ((_vMin + _vMax) / 2);};
|
||||
public: DbU::Unit getSize() const {return (isEmpty() ? 0 : (_vMax - _vMin));};
|
||||
public: DbU::Unit getSize() const;
|
||||
public: DbU::Unit getHalfSize() const {return (getSize() / 2);};
|
||||
public: Interval getUnion(const Interval& interval) const;
|
||||
public: Interval getIntersection(const Interval& interval) const;
|
||||
|
@ -72,6 +72,7 @@ class Interval {
|
|||
// **********
|
||||
|
||||
public: bool isEmpty() const { return (_vMax < _vMin);};
|
||||
public: bool isFull() const { return (_vMin == DbU::Min) and (_vMax == DbU::Max); };
|
||||
public: bool isPonctual() const { return (_vMax == _vMin);};
|
||||
public: bool contains(const DbU::Unit& v) const;
|
||||
public: bool contains(const Interval& interval) const;
|
||||
|
@ -104,6 +105,14 @@ class Interval {
|
|||
};
|
||||
|
||||
|
||||
inline DbU::Unit Interval::getSize () const
|
||||
{
|
||||
if (isEmpty()) return 0;
|
||||
if (isFull ()) return DbU::Max;
|
||||
return _vMax - _vMin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // End of Hurricane namespace.
|
||||
|
||||
|
|
|
@ -52,6 +52,13 @@ namespace Hurricane {
|
|||
class Layer : public DBo {
|
||||
public:
|
||||
typedef DBo Super;
|
||||
public:
|
||||
static const uint32_t NoFlags = 0;
|
||||
static const uint32_t EnclosureH = (1 << 0);
|
||||
static const uint32_t EnclosureV = (1 << 1);
|
||||
static const uint32_t EnclosureMax = (1 << 2);
|
||||
static const uint32_t ExtensionCap = (1 << 3);
|
||||
static const uint32_t ExtensionWidth = (1 << 4);
|
||||
|
||||
public:
|
||||
// Types.
|
||||
|
@ -72,12 +79,14 @@ namespace Hurricane {
|
|||
Layer* getMetalBelow ( bool useSymbolic=true ) const;
|
||||
Layer* getCutAbove ( bool useSymbolic=true ) const;
|
||||
Layer* getCutBelow ( bool useSymbolic=true ) const;
|
||||
virtual DbU::Unit getEnclosure () const;
|
||||
virtual DbU::Unit getEnclosure ( uint32_t flags ) const;
|
||||
virtual DbU::Unit getExtentionCap () const;
|
||||
virtual DbU::Unit getExtentionWidth () const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const;
|
||||
virtual DbU::Unit getExtentionCap ( const BasicLayer* layer ) const;
|
||||
virtual DbU::Unit getExtentionWidth ( const BasicLayer* layer ) const;
|
||||
virtual DbU::Unit getTopEnclosure ( uint32_t flags ) const;
|
||||
virtual DbU::Unit getBottomEnclosure ( uint32_t flags ) const;
|
||||
// Predicates
|
||||
inline bool above ( const Layer* layer ) const;
|
||||
inline bool below ( const Layer* layer ) const;
|
||||
|
@ -89,7 +98,7 @@ namespace Hurricane {
|
|||
inline void setSymbolic ( bool );
|
||||
void setMinimalSize ( const DbU::Unit& minimalSize );
|
||||
void setMinimalSpacing ( const DbU::Unit& minimalSpacing );
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit );
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit, uint32_t flags );
|
||||
virtual void setExtentionCap ( const BasicLayer* layer, DbU::Unit );
|
||||
virtual void setExtentionWidth ( const BasicLayer* layer, DbU::Unit );
|
||||
// Hurricane Managment.
|
||||
|
|
|
@ -60,7 +60,8 @@ namespace Hurricane {
|
|||
public:
|
||||
// Accessors.
|
||||
bool isPlacedOccurrence ( unsigned int flags ) const;
|
||||
inline Occurrence getOccurrence () const { return _occurrence; };
|
||||
inline bool isAtTopLevel () const;
|
||||
inline Occurrence getOccurrence () const;
|
||||
Occurrence getPlugOccurrence ();
|
||||
virtual const Layer* getLayer () const;
|
||||
virtual DbU::Unit getX () const;
|
||||
|
@ -98,6 +99,10 @@ namespace Hurricane {
|
|||
};
|
||||
|
||||
|
||||
inline bool RoutingPad::isAtTopLevel () const { return _occurrence.getPath().isEmpty(); }
|
||||
inline Occurrence RoutingPad::getOccurrence () const { return _occurrence; };
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "JsonRoutingPad".
|
||||
|
||||
|
|
|
@ -60,10 +60,12 @@ namespace Hurricane {
|
|||
virtual const Layer* getTop () const;
|
||||
virtual const Layer* getBottom () const;
|
||||
virtual const Layer* getOpposite ( const Layer* ) const;
|
||||
virtual DbU::Unit getEnclosure () const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer ) const;
|
||||
virtual DbU::Unit getEnclosure ( uint32_t flags ) const;
|
||||
virtual DbU::Unit getEnclosure ( const BasicLayer* layer, uint32_t flags ) const;
|
||||
virtual DbU::Unit getTopEnclosure ( uint32_t flags ) const;
|
||||
virtual DbU::Unit getBottomEnclosure ( uint32_t flags ) const;
|
||||
// Updators.
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure );
|
||||
virtual void setEnclosure ( const BasicLayer* layer, DbU::Unit enclosure, uint32_t flags );
|
||||
// Hurricane Managment.
|
||||
virtual void _toJson ( JsonWriter* ) const;
|
||||
virtual void _onDbuChange ( float scale );
|
||||
|
@ -74,7 +76,7 @@ namespace Hurricane {
|
|||
private:
|
||||
// Internal: Attributes
|
||||
vector<BasicLayer*> _basicLayers;
|
||||
vector<DbU::Unit> _enclosures;
|
||||
vector< pair<DbU::Unit,DbU::Unit> > _enclosures;
|
||||
DbU::Unit _maximalEnclosure;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -240,13 +240,79 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyLayer_getEnclosure ( PyLayer* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(20,0) << "PyLayer_getEnclosure()" << endl;
|
||||
|
||||
DbU::Unit rvalue = 0;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD("Layer.getEnclosure()")
|
||||
|
||||
PyObject* arg0 = NULL;
|
||||
PyObject* arg1 = NULL;
|
||||
|
||||
__cs.init( "Layer.getEnclosure()" );
|
||||
if (PyArg_ParseTuple( args, "O&|O&:Layer.getEnclosure()"
|
||||
, Converter, &arg0
|
||||
, Converter, &arg1 )) {
|
||||
if (__cs.getObjectIds() == ":basiclayer:int")
|
||||
rvalue = layer->getEnclosure( PYBASICLAYER_O(arg0), PyAny_AsLong(arg1) );
|
||||
else if ( __cs.getObjectIds() == ":int" )
|
||||
rvalue = layer->getEnclosure( PyAny_AsLong(arg1) );
|
||||
else {
|
||||
PyErr_SetString ( ConstructorError
|
||||
, "invalid parameter type for Layer.getEnclosure()." );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString ( ConstructorError
|
||||
, "Invalid number of parameters passed to Layer.getEnclosure()." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
return PyLong_FromLong(rvalue);
|
||||
}
|
||||
|
||||
|
||||
static PyObject* PyLayer_setEnclosure ( PyLayer* self, PyObject* args )
|
||||
{
|
||||
cdebug_log(20,0) << "PyLayer_setEnclosure()" << endl;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD("PyLayer.setEnclosure()")
|
||||
|
||||
PyObject* pyBasicLayer = NULL;
|
||||
PyObject* pyDimension = NULL;
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (PyArg_ParseTuple( args, "OOi:Layer.setEnclosure()"
|
||||
, &pyBasicLayer, &pyDimension, &flags )) {
|
||||
BasicLayer* basicLayer = PYBASICLAYER_O(pyBasicLayer);
|
||||
if (basicLayer == NULL) {
|
||||
PyErr_SetString( ConstructorError
|
||||
, "Layer.setEnclosure(): First parameter is not of BasicLayer type" );
|
||||
return NULL;
|
||||
}
|
||||
layer->setEnclosure( basicLayer, PyAny_AsLong(pyDimension), flags );
|
||||
} else {
|
||||
PyErr_SetString( ConstructorError
|
||||
, "Layer.setEnclosure(): Bad parameters types or numbers." );
|
||||
return NULL;
|
||||
}
|
||||
HCATCH
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
GetNameMethod (Layer, layer)
|
||||
predicateFromLayer ( above ,PyLayer,Layer)
|
||||
predicateFromLayer ( below ,PyLayer,Layer)
|
||||
predicateFromLayer ( contains ,PyLayer,Layer)
|
||||
predicateFromLayer ( intersect ,PyLayer,Layer)
|
||||
predicateFromVoid ( isSymbolic ,PyLayer,Layer)
|
||||
accessorDbuFromOptBasicLayer( getEnclosure ,PyLayer,Layer)
|
||||
accessorDbuFromOptBasicLayer( getExtentionCap ,PyLayer,Layer)
|
||||
accessorDbuFromOptBasicLayer( getExtentionWidth,PyLayer,Layer)
|
||||
accessorCollectionFromVoid ( getBasicLayers ,PyLayer,Layer,BasicLayer)
|
||||
|
@ -266,7 +332,6 @@ extern "C" {
|
|||
SetNameMethod(Layer, layer)
|
||||
updatorFromDbu (setMinimalSize ,PyLayer,Layer)
|
||||
updatorFromDbu (setMinimalSpacing,PyLayer,Layer)
|
||||
updatorFromBasicLayerDbu(setEnclosure ,PyLayer,Layer)
|
||||
updatorFromBasicLayerDbu(setExtentionCap ,PyLayer,Layer)
|
||||
updatorFromBasicLayerDbu(setExtentionWidth,PyLayer,Layer)
|
||||
DirectSetBoolAttribute (PyLayer_setSymbolic,setSymbolic,PyLayer,Layer)
|
||||
|
@ -366,6 +431,15 @@ extern "C" {
|
|||
extern void PyLayer_postModuleInit ()
|
||||
{
|
||||
PyDict_SetItemString ( PyTypeLayer.tp_dict, "Mask", (PyObject*)&PyTypeLayerMask );
|
||||
|
||||
PyObject* constant;
|
||||
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::NoFlags ,"NoFlags" );
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureH ,"EnclosureH" );
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureV ,"EnclosureV" );
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::EnclosureMax ,"EnclosureMax" );
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::ExtensionCap ,"ExtensionCap" );
|
||||
LoadObjectConstant(PyTypeLayer.tp_dict,Layer::ExtensionWidth,"ExtensionWidth");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "hurricane/DebugSession.h"
|
||||
#include "anabatic/AutoSegment.h"
|
||||
#include "katana/DataNegociate.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/RoutingEvent.h"
|
||||
#include "katana/KatanaEngine.h"
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
@ -137,15 +139,37 @@ namespace Katana {
|
|||
//interval.inflate( DbU::fromLambda(-0.5) );
|
||||
|
||||
cdebug_log(159,0) << "| perpandicular: " << perpandiculars[i] << endl;
|
||||
cdebug_log(159,0) << "| canonical: " << perpandicular << endl;
|
||||
cdebug_log(159,1) << "Canonical // interval: " << interval << endl;
|
||||
cdebug_log(159,1) << "| canonical: " << perpandicular << endl;
|
||||
cdebug_log(159,0) << "Canonical // interval: " << interval << endl;
|
||||
|
||||
_perpandiculars.push_back( perpandicular );
|
||||
if (perpandicular->getTrack()) {
|
||||
Interval trackFree = perpandicular->getFreeInterval();
|
||||
cdebug_log(159,0) << "Track Perpandicular Free: " << trackFree << endl;
|
||||
|
||||
_perpandicularFree.intersection( trackFree.inflate(-perpandicular->getExtensionCap()) );
|
||||
_perpandicularFree.intersection
|
||||
( trackFree.inflate ( -perpandicular->getExtensionCap(Flags::Source)
|
||||
, -perpandicular->getExtensionCap(Flags::Target)) );
|
||||
cdebug_log(159,0) << "Source cap:"
|
||||
<< DbU::getValueString(perpandicular->getExtensionCap(Flags::Source)) << endl;
|
||||
} else if (perpandicular->isFixedAxis()) {
|
||||
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(perpandicular->getLayer());
|
||||
Track* track = plane->getTrackByPosition( perpandicular->getAxis() );
|
||||
if (track and (perpandicular->getAxis() == track->getAxis())) {
|
||||
Interval trackFree = track->getFreeInterval( perpandicular->getSourceU(), _trackSegment->getNet() );
|
||||
cdebug_log(159,0) << "SourceU: " << DbU::getValueString(perpandicular->getSourceU()) << endl;
|
||||
cdebug_log(159,0) << "Track Perpandicular Free (fixed axis, source): " << trackFree << endl;
|
||||
|
||||
if (trackFree.isEmpty()) {
|
||||
trackFree = track->getFreeInterval( perpandicular->getTargetU(), _trackSegment->getNet() );
|
||||
cdebug_log(159,0) << "TargetU: " << DbU::getValueString(perpandicular->getTargetU()) << endl;
|
||||
cdebug_log(159,0) << "Track Perpandicular Free (fixed axis, target): " << trackFree << endl;
|
||||
}
|
||||
|
||||
_perpandicularFree.intersection
|
||||
( trackFree.inflate ( -perpandicular->getExtensionCap(Flags::Source)
|
||||
, -perpandicular->getExtensionCap(Flags::Target)) );
|
||||
}
|
||||
} else {
|
||||
cdebug_log(159,0) << "Not in any track " << perpandicular << endl;
|
||||
}
|
||||
|
@ -252,10 +276,10 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
string DataNegociate::getStateString ( DataNegociate* data )
|
||||
string DataNegociate::getStateString ( uint32_t state, unsigned int stateCount )
|
||||
{
|
||||
ostringstream s;
|
||||
switch ( data->_state ) {
|
||||
switch ( state ) {
|
||||
case RipupPerpandiculars: s << "RipupPerpandiculars"; break;
|
||||
case Minimize: s << "Minimize"; break;
|
||||
case Dogleg: s << "Dogleg"; break;
|
||||
|
@ -266,13 +290,20 @@ namespace Katana {
|
|||
case MoveUp: s << "MoveUp"; break;
|
||||
case MaximumSlack: s << "MaximumSlack"; break;
|
||||
case Unimplemented: s << "Unimplemented"; break;
|
||||
case Repair: s << "REPAIR"; break;
|
||||
case Repair: s << "Repair"; break;
|
||||
case RepairFailed: s << "RepairFailed"; break;
|
||||
default:
|
||||
s << "Unknown(" << data->_state << ")"; break;
|
||||
s << "Unknown(" << state << ")"; break;
|
||||
}
|
||||
s << ":" << data->_stateCount;
|
||||
s << ":" << stateCount;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
string DataNegociate::getStateString ( DataNegociate* data )
|
||||
{
|
||||
return getStateString( data->_state, data->_stateCount );
|
||||
}
|
||||
|
||||
|
||||
} // Katana namespace.
|
||||
|
|
|
@ -143,21 +143,21 @@ namespace Katana {
|
|||
|
||||
bool Manipulator::ripup ( uint32_t type, DbU::Unit axisHint )
|
||||
{
|
||||
cdebug_log(159,0) << "Manipulator::ripup() " << endl;
|
||||
cdebug_log(159,1) << "Manipulator::ripup()" << endl;
|
||||
|
||||
if (not canRipup()) return false;
|
||||
|
||||
if (_segment->isFixed()) return false;
|
||||
if (_data == NULL) return true;
|
||||
if (not canRipup()) { cdebug_tabw(159,-1); return false; }
|
||||
if (_segment->isFixed()) { cdebug_tabw(159,-1); return false; }
|
||||
if (_data == NULL) { cdebug_tabw(159,-1); return true; }
|
||||
|
||||
_fsm.addAction( _segment, type, axisHint );
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Manipulator::ripupPerpandiculars ( uint32_t flags )
|
||||
{
|
||||
cdebug_log(159,0) << "Manipulator::ripupPerpandiculars() - " << flags << endl;
|
||||
cdebug_log(159,1) << "Manipulator::ripupPerpandiculars() - " << flags << endl;
|
||||
|
||||
bool success = true;
|
||||
bool cagedPerpandiculars = false;
|
||||
|
@ -183,6 +183,8 @@ namespace Katana {
|
|||
const vector<TrackElement*>& perpandiculars = _event->getPerpandiculars();
|
||||
|
||||
for ( size_t i=0 ; i < perpandiculars.size() ; i++ ) {
|
||||
cdebug_log(159,0) << "| " << perpandiculars[i] << endl;
|
||||
|
||||
track = perpandiculars[i]->getTrack();
|
||||
if (not track) {
|
||||
// The perpandicular is not placed yet.
|
||||
|
@ -202,10 +204,11 @@ namespace Katana {
|
|||
|
||||
// Try to ripup the perpandicular.
|
||||
DataNegociate* data2 = perpandiculars[i]->getDataNegociate();
|
||||
cdebug_log(159,0) << "| " << perpandiculars[i] << endl;
|
||||
|
||||
if ( (flags & Manipulator::ToMoveUp) and (data2->getState() < DataNegociate::MoveUp) )
|
||||
if ( (flags & Manipulator::ToMoveUp) and (data2->getState() < DataNegociate::MoveUp) ) {
|
||||
cdebug_log(159,0) << "Force move up of perpandicular." << endl;
|
||||
data2->setState( DataNegociate::MoveUp );
|
||||
}
|
||||
|
||||
if (Manipulator(perpandiculars[i],_fsm).ripup(perpandicularActionFlags)) {
|
||||
if (dislodgeCaged) {
|
||||
|
@ -215,6 +218,7 @@ namespace Katana {
|
|||
}
|
||||
|
||||
// Cannot ripup the perpandicular, try to ripup it's neigbors.
|
||||
cdebug_log(159,0) << "Try to ripup neighbors." << endl;
|
||||
size_t begin;
|
||||
size_t end;
|
||||
track->getOverlapBounds( constraints, begin, end );
|
||||
|
@ -233,6 +237,7 @@ namespace Katana {
|
|||
_fsm.addAction( other, SegmentAction::OtherRipup );
|
||||
} else {
|
||||
cdebug_log(159,0) << "Aborted ripup of perpandiculars, fixed or blocked." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -241,6 +246,7 @@ namespace Katana {
|
|||
if (cagedPerpandiculars and not placedPerpandiculars) {
|
||||
cdebug_log(159,0) << "Aborted ripup of perpandiculars, constraints are due to fixed/blockage." << endl;
|
||||
_fsm.addAction( _segment, SegmentAction::SelfRipup );
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -250,6 +256,7 @@ namespace Katana {
|
|||
_fsm.addAction( perpandiculars[i], perpandicularActionFlags|SegmentAction::EventLevel4 );
|
||||
}
|
||||
_fsm.addAction( _segment, parallelActionFlags );
|
||||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -265,13 +272,15 @@ namespace Katana {
|
|||
if (_segment->isLocal() and (tracksNb < 2)) success = ripple();
|
||||
|
||||
_fsm.addAction( _segment, parallelActionFlags );
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool Manipulator::relax ( Interval interval, uint32_t flags )
|
||||
{
|
||||
interval.inflate( - Session::getExtensionCap(getLayer()) );
|
||||
Session::toAxisInterval( interval, Session::getLayerDepth(_segment->getLayer())+1 );
|
||||
cdebug_log(159,0) << "Manipulator::relax() of: " << _segment << " " << interval << endl;
|
||||
|
||||
if (_segment->isFixed()) return false;
|
||||
|
@ -784,7 +793,7 @@ 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()) ) {
|
||||
if ( segment3->getAxis() == segment2->getTargetAxis() ) {
|
||||
//leftIntrication = true;
|
||||
//leftAxisHint = segment3->getAxis();
|
||||
}
|
||||
|
@ -802,7 +811,7 @@ namespace Katana {
|
|||
break;
|
||||
if ( event3->getTracksFree() == 1 ) {
|
||||
cdebug_log(159,0) << "Potential right intrication with other perpandicular." << endl;
|
||||
if ( segment3->getAxis() == segment2->getSourceU() + Session::getExtensionCap(getLayer()) ) {
|
||||
if ( segment3->getAxis() == segment2->getSourceAxis() ) {
|
||||
//rightIntrication = true;
|
||||
//rightAxisHint = segment3->getAxis();
|
||||
}
|
||||
|
@ -1162,7 +1171,7 @@ namespace Katana {
|
|||
} else {
|
||||
if (not _segment->canMoveUp(0.5,kflags)) return false;
|
||||
}
|
||||
return _segment->moveUp( kflags );
|
||||
return _segment->moveUp( kflags|Flags::Propagate );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1463,6 +1472,7 @@ namespace Katana {
|
|||
Track* track = _fsm.getTrack( 0 );
|
||||
DbU::Unit axisHint = 0;
|
||||
|
||||
#if DISABLED
|
||||
if (termConstraints.getSize() < _segment->getPPitch()*2) {
|
||||
cdebug_log(159,0) << "Constraints less than two perpandicular pitches, lock." << endl;
|
||||
|
||||
|
@ -1475,12 +1485,18 @@ namespace Katana {
|
|||
cdebug_tabw(159,-1);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for ( ; begin < end ; ++begin ) {
|
||||
TrackElement* conflict = track->getSegment(begin);
|
||||
if (conflict->getCanonicalInterval().intersect( _segment->getCanonicalInterval() )) break;
|
||||
}
|
||||
|
||||
if (begin == end) {
|
||||
axisHint = termConstraints.getCenter();
|
||||
cdebug_log(159,0) << "No conflict under canonical interval (?) use terminal center." << endl;
|
||||
cdebug_log(159,0) << "term: " << termConstraints << " center:" << DbU::getValueString(axisHint) << endl;
|
||||
} else {
|
||||
Interval previousFree = track->getPreviousFree( begin, _segment->getNet() );
|
||||
if (previousFree.intersect(termConstraints))
|
||||
axisHint = previousFree.getCenter();
|
||||
|
@ -1496,6 +1512,7 @@ namespace Katana {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Axis Hint: " << DbU::getValueString(axisHint) << endl;
|
||||
|
||||
|
@ -1512,6 +1529,8 @@ namespace Katana {
|
|||
_fsm.addAction( perpandiculars[i], SegmentAction::SelfRipupPerpandWithAxisHint, axisHint );
|
||||
}
|
||||
|
||||
//_fsm.addAction( _segment, SegmentAction::SelfRipup|SegmentAction::EventLevel3 );
|
||||
|
||||
_event->setMinimized();
|
||||
|
||||
cdebug_tabw(159,-1);
|
||||
|
@ -1536,12 +1555,11 @@ namespace Katana {
|
|||
if ( not Manipulator(perpandicular,_fsm).canRipup()
|
||||
or (data->getState() >= DataNegociate::MaximumSlack) ) continue;
|
||||
|
||||
// Ugly: ExtensionCap usage.
|
||||
if ( moveLeft ) {
|
||||
if ( perpandicular->getTargetU()-Session::getExtensionCap(getLayer()) == _event->getAxisHistory() )
|
||||
if ( perpandicular->getTargetAxis() == _event->getAxisHistory() )
|
||||
_fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking );
|
||||
} else {
|
||||
if ( perpandicular->getSourceU()+Session::getExtensionCap(getLayer()) == _event->getAxisHistory() )
|
||||
if ( perpandicular->getSourceAxis() == _event->getAxisHistory() )
|
||||
_fsm.addAction ( perpandicular, SegmentAction::OtherRipupPerpandAndPacking );
|
||||
}
|
||||
}
|
||||
|
@ -1560,6 +1578,7 @@ namespace Katana {
|
|||
if (perpandicular->isFixed ()) continue;
|
||||
if (perpandicular->isGlobal()) continue;
|
||||
if (not data) continue;
|
||||
if (data->getState() >= DataNegociate::RepairFailed) continue;
|
||||
|
||||
if (RoutingEvent::getStage() == RoutingEvent::Repair) {
|
||||
data->setState( DataNegociate::Repair );
|
||||
|
|
|
@ -117,6 +117,7 @@ namespace {
|
|||
{
|
||||
AllianceFramework* af = AllianceFramework::get ();
|
||||
RoutingGauge* rg = nw->getKatanaEngine()->getConfiguration()->getRoutingGauge();
|
||||
bool isVH = rg->isVH();
|
||||
|
||||
for( Net* net : nw->getCell()->getNets() ) {
|
||||
if (net->getType() == Net::Type::POWER ) continue;
|
||||
|
@ -126,9 +127,13 @@ namespace {
|
|||
|
||||
for( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
size_t depth = rg->getLayerDepth(rp->getLayer());
|
||||
if (depth > 0) continue;
|
||||
if (depth == 0)
|
||||
if (depth == 0) {
|
||||
TrackMarker::create( rp, 1 );
|
||||
//if (isVH) TrackMarker::create( rp, 2 );
|
||||
}
|
||||
if (depth == 1) {
|
||||
TrackMarker::create( rp, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,9 +516,6 @@ namespace Katana {
|
|||
}
|
||||
}
|
||||
|
||||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
count++;
|
||||
|
||||
if (tty::enabled()) {
|
||||
cmess2 << " <event:" << tty::bold << right << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << tty::reset
|
||||
|
@ -530,6 +532,9 @@ namespace Katana {
|
|||
cmess2.flush();
|
||||
}
|
||||
|
||||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
count++;
|
||||
|
||||
//if (count and not (count % 500)) {
|
||||
// _pack( count, false );
|
||||
//}
|
||||
|
@ -580,7 +585,7 @@ namespace Katana {
|
|||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
|
||||
count++;
|
||||
if (RoutingEvent::getProcesseds() >= limit ) setInterrupt( true );
|
||||
if (RoutingEvent::getProcesseds() >= limit) setInterrupt( true );
|
||||
}
|
||||
|
||||
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
|
||||
|
|
|
@ -383,49 +383,6 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
@ -452,8 +409,6 @@ namespace Katana {
|
|||
}
|
||||
}
|
||||
|
||||
for ( GCell* gcell : getGCells() ) protectAlignedAccesses( gcell );
|
||||
|
||||
//DebugSession::close();
|
||||
|
||||
Session::revalidate ();
|
||||
|
|
|
@ -68,7 +68,14 @@ namespace Katana {
|
|||
bool RoutingEvent::Compare::operator() ( const RoutingEvent* lhs, const RoutingEvent* rhs ) const
|
||||
{
|
||||
if (lhs == rhs) return false;
|
||||
return RoutingEvent::Key::Compare()( lhs->getKey(), rhs->getKey() );
|
||||
bool value = RoutingEvent::Key::Compare()( lhs->getKey(), rhs->getKey() );
|
||||
// if ( (lhs->getSegment()->base()->getFlags() & AutoSegment::SegFixedAxis)
|
||||
// or (lhs->getSegment()->base()->getFlags() & AutoSegment::SegFixedAxis)) {
|
||||
// cerr << "Compare: lhs < rhs = " << value << endl;
|
||||
// cerr << " lhs L:" << lhs->getEventLevel() << " " << lhs << endl;
|
||||
// cerr << " rhs L:" << rhs->getEventLevel() << " " << rhs << endl;
|
||||
// }
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,6 +94,11 @@ namespace Katana {
|
|||
// Process all M2 (terminal access) before any others.
|
||||
//if ((lhs._layerDepth == 1) and (rhs._layerDepth != 1)) return false;
|
||||
//if ((lhs._layerDepth != 1) and (rhs._layerDepth == 1)) return true;
|
||||
|
||||
// For VH gauge, process fixed axis first.
|
||||
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._layerDepth > rhs._layerDepth) return true;
|
||||
if (lhs._layerDepth < rhs._layerDepth) return false;
|
||||
|
||||
|
@ -317,6 +329,11 @@ namespace Katana {
|
|||
|
||||
RoutingEvent* fork = NULL;
|
||||
|
||||
if (getState() == DataNegociate::RepairFailed) {
|
||||
cdebug_log(159,0) << "Reschedule: cancelled (RepairFailed) -> " << fork << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (getStage() != Repair) and isUnimplemented() ) {
|
||||
cdebug_log(159,0) << "Reschedule: cancelled (Unimplemented) -> " << fork << endl;
|
||||
return NULL;
|
||||
|
@ -332,7 +349,8 @@ namespace Katana {
|
|||
|
||||
_segment->getDataNegociate()->setRoutingEvent( fork );
|
||||
|
||||
cdebug_log(159,0) << "Reschedule/Fork: -> " << fork << endl;
|
||||
cdebug_log(159,0) << "Reschedule/Fork: -> "
|
||||
<< eventLevel << ":" << fork << endl;
|
||||
}
|
||||
|
||||
if (fork->_eventLevel < eventLevel)
|
||||
|
@ -364,10 +382,8 @@ namespace Katana {
|
|||
, RoutingEventLoop& loop
|
||||
)
|
||||
{
|
||||
loop.update( _segment->getId() );
|
||||
loop.update( _segment );
|
||||
if (loop.isLooping()) {
|
||||
loop.erase( _segment->getId() );
|
||||
setState( DataNegociate::Unimplemented );
|
||||
|
||||
#if LOOP_DEBUG
|
||||
if (loop.getMaxCount() > 500) {
|
||||
|
@ -391,13 +407,18 @@ namespace Katana {
|
|||
|
||||
const vector<RoutingEventLoop::Element>& elements = loop.getElements();
|
||||
for ( size_t i=0 ; i<elements.size() ; ++i ) {
|
||||
message << "\n" << setw(10) << elements[i]._count << "| id:" << elements[i]._id;
|
||||
message << "\n" << setw(10) << elements[i]._count << "| " << elements[i]._segment;
|
||||
}
|
||||
cbug << message.str() << endl;
|
||||
cerr << message.str() << endl;
|
||||
#endif
|
||||
|
||||
loop.erase( _segment );
|
||||
setState( DataNegociate::RepairFailed );
|
||||
setDisabled( true );
|
||||
}
|
||||
|
||||
DebugSession::open( _segment->getNet(), 155, 160 );
|
||||
//DebugSession::open( _segment->getNet(), 155, 160 );
|
||||
DebugSession::open( _segment->getNet(), 149, 160 );
|
||||
|
||||
cdebug_log(9000,0) << "Deter| Event "
|
||||
<< getProcesseds()
|
||||
|
@ -591,6 +612,7 @@ namespace Katana {
|
|||
break;
|
||||
default:
|
||||
cdebug_log(159,0) << "Repair failed." << endl;
|
||||
setState( DataNegociate::RepairFailed );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ namespace Katana {
|
|||
using std::stable_sort;
|
||||
|
||||
|
||||
size_t RoutingEventLoop::Element::getId () const
|
||||
{ return _segment->getId(); }
|
||||
|
||||
|
||||
RoutingEventLoop::RoutingEventLoop ( size_t depth, int countLimit )
|
||||
: _elements ()
|
||||
, _depth (depth)
|
||||
|
@ -37,37 +41,37 @@ namespace Katana {
|
|||
{ }
|
||||
|
||||
|
||||
void RoutingEventLoop::update ( size_t id )
|
||||
void RoutingEventLoop::update ( TrackElement* segment )
|
||||
{
|
||||
vector<Element>::iterator ielement = _elements.begin();
|
||||
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||
if ( (*ielement)._id == id ) {
|
||||
if ((*ielement).getId() == segment->getId()) {
|
||||
// Increment an already present element.
|
||||
(*ielement)._count += 1;
|
||||
(*ielement)._timestamp = RoutingEvent::getProcesseds();
|
||||
_maxCount = std::max ( _maxCount, (*ielement)._count );
|
||||
|
||||
if ( _maxCount > _countLimit ) _isLooping = true;
|
||||
if (_maxCount > _countLimit) _isLooping = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The Event was not found.
|
||||
if ( ielement == _elements.end() ) {
|
||||
if ( _elements.size() >= _depth ) _elements.pop_back ();
|
||||
_elements.push_back ( Element(id,RoutingEvent::getProcesseds()) );
|
||||
if (ielement == _elements.end()) {
|
||||
if (_elements.size() >= _depth) _elements.pop_back();
|
||||
_elements.push_back( Element(segment,RoutingEvent::getProcesseds()) );
|
||||
}
|
||||
|
||||
stable_sort ( _elements.begin(), _elements.end(), CompareByTimestamp() );
|
||||
stable_sort( _elements.begin(), _elements.end(), CompareByTimestamp() );
|
||||
}
|
||||
|
||||
|
||||
void RoutingEventLoop::erase ( size_t id )
|
||||
void RoutingEventLoop::erase ( TrackElement* segment )
|
||||
{
|
||||
vector<Element>::iterator ielement = _elements.begin();
|
||||
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||
if ( (*ielement)._id == id ) {
|
||||
_elements.erase ( ielement );
|
||||
if ((*ielement).getId() == segment->getId()) {
|
||||
_elements.erase( ielement );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +79,7 @@ namespace Katana {
|
|||
_maxCount = 0;
|
||||
ielement = _elements.begin();
|
||||
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||
_maxCount = std::max ( _maxCount, (*ielement)._count );
|
||||
_maxCount = std::max( _maxCount, (*ielement)._count );
|
||||
}
|
||||
|
||||
_isLooping = (_maxCount > _countLimit);
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace Katana {
|
|||
if (plane->getDirection() == Flags::Horizontal) {
|
||||
plane->_tracks.push_back( HorizontalTrack::create( plane, index ) );
|
||||
// Ugly: Direct uses of CellGauge (middle tracks 4 & 5 for local use).
|
||||
if (depth == 1) {
|
||||
if ( (depth == 1) and not Session::getRoutingGauge()->isVH() ) {
|
||||
switch ( index%10 ) {
|
||||
case 4:
|
||||
case 5:
|
||||
|
|
|
@ -456,9 +456,10 @@ namespace Katana {
|
|||
, _optimal ()
|
||||
, _costs ()
|
||||
, _actions ()
|
||||
, _fullBlocked(true)
|
||||
, _fullBlocked (true)
|
||||
, _sameAxis (false)
|
||||
, _useEvent2 (false)
|
||||
, _minimizeDrag(false)
|
||||
{
|
||||
DataSymmetric* symData = NULL;
|
||||
TrackElement* segment1 = _event1->getSegment();
|
||||
|
@ -1184,44 +1185,60 @@ namespace Katana {
|
|||
|
||||
switch (data->getState()) {
|
||||
case DataNegociate::RipupPerpandiculars:
|
||||
if (segment->isDrag() and getCost(0)->isInfinite()) {
|
||||
nextState = DataNegociate::Slacken;
|
||||
success = manipulator.dragMinimize();
|
||||
if (success) _minimizeDrag = true;
|
||||
} else {
|
||||
nextState = DataNegociate::Minimize;
|
||||
success = manipulator.ripupPerpandiculars();
|
||||
}
|
||||
if (success) break;
|
||||
case DataNegociate::Minimize:
|
||||
if (nextState == DataNegociate::Minimize) {
|
||||
if (isFullBlocked() and not segment->isTerminal()) {
|
||||
cdebug_log(159,0) << "Is Fully blocked." << endl;
|
||||
nextState = DataNegociate::Unimplemented;
|
||||
break;
|
||||
}
|
||||
nextState = DataNegociate::Dogleg;
|
||||
// if (segment->isDrag())
|
||||
// success = manipulator.dragMinimize();
|
||||
// else
|
||||
success = manipulator.minimize();
|
||||
if (success) break;
|
||||
}
|
||||
case DataNegociate::Dogleg:
|
||||
if (nextState == DataNegociate::Dogleg) {
|
||||
nextState = DataNegociate::Slacken;
|
||||
success = manipulator.makeDogleg();
|
||||
if (success) break;
|
||||
}
|
||||
case DataNegociate::Slacken:
|
||||
if (nextState == DataNegociate::Slacken) {
|
||||
nextState = DataNegociate::ConflictSolveByPlaceds;
|
||||
success = manipulator.slacken();
|
||||
if (success) break;
|
||||
}
|
||||
case DataNegociate::ConflictSolveByHistory:
|
||||
case DataNegociate::ConflictSolveByPlaceds:
|
||||
if ( (nextState == DataNegociate::ConflictSolveByHistory)
|
||||
or (nextState == DataNegociate::ConflictSolveByPlaceds) ) {
|
||||
nextState = DataNegociate::LocalVsGlobal;
|
||||
success = conflictSolveByHistory();
|
||||
break;
|
||||
}
|
||||
case DataNegociate::LocalVsGlobal:
|
||||
if (nextState == DataNegociate::LocalVsGlobal) {
|
||||
nextState = DataNegociate::MoveUp;
|
||||
success = solveTerminalVsGlobal();
|
||||
if (success) break;
|
||||
break;
|
||||
}
|
||||
case DataNegociate::MoveUp:
|
||||
if (nextState == DataNegociate::LocalVsGlobal) {
|
||||
nextState = DataNegociate::MaximumSlack;
|
||||
success = manipulator.moveUp();
|
||||
if (success) break;
|
||||
}
|
||||
case DataNegociate::MaximumSlack:
|
||||
if (nextState == DataNegociate::MaximumSlack) {
|
||||
if (segment->isStrap()) {
|
||||
if ( (nextState < DataNegociate::MaximumSlack) or (data->getStateCount() < 2) ) {
|
||||
nextState = DataNegociate::MaximumSlack;
|
||||
|
@ -1229,8 +1246,9 @@ namespace Katana {
|
|||
if (success) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
case DataNegociate::Unimplemented:
|
||||
if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl;
|
||||
//if (segment->isDrag()) cerr << "Slacken DRAG:" << segment << endl;
|
||||
nextState = DataNegociate::Unimplemented;
|
||||
break;
|
||||
}
|
||||
|
@ -1249,7 +1267,8 @@ namespace Katana {
|
|||
|
||||
if (not (flags&NoTransition)) {
|
||||
data->setState( nextState );
|
||||
cdebug_log(159,0) << "Incrementing state (after): " << nextState << " count:" << data->getStateCount() << endl;
|
||||
cdebug_log(159,0) << "Incrementing state (after): "
|
||||
<< DataNegociate::getStateString(nextState,data->getStateCount()) << endl;
|
||||
}
|
||||
|
||||
return success;
|
||||
|
@ -1384,6 +1403,10 @@ namespace Katana {
|
|||
|
||||
if (success) {
|
||||
actionFlags |= SegmentAction::ResetRipup;
|
||||
if (isMinimizeDrag()) {
|
||||
actionFlags &= ~SegmentAction::EventLevel5;
|
||||
actionFlags |= SegmentAction::EventLevel3;
|
||||
}
|
||||
addAction( segment1, actionFlags );
|
||||
} else {
|
||||
clearActions();
|
||||
|
|
|
@ -181,6 +181,23 @@ namespace Katana {
|
|||
{ return _getKatanaEngine()->getGCellUnder(Point(x,y)); };
|
||||
|
||||
|
||||
Interval& Session::_toAxisInterval ( Interval& interval, size_t depth ) const
|
||||
{
|
||||
RoutingLayerGauge* rg = getLayerGauge(depth);
|
||||
if (not rg) return interval;
|
||||
|
||||
Box ab = getKatanaEngine()->getCell()->getAbutmentBox();
|
||||
DbU::Unit abMin = (rg->isHorizontal()) ? ab.getYMin() : ab.getXMin();
|
||||
DbU::Unit abMax = (rg->isHorizontal()) ? ab.getYMax() : ab.getXMax() ;
|
||||
|
||||
DbU::Unit trackMin = rg->getTrackPosition( abMin, abMax, interval.getVMin(), Constant::Superior );
|
||||
DbU::Unit trackMax = rg->getTrackPosition( abMin, abMax, interval.getVMax(), Constant::Inferior );
|
||||
interval = Interval( trackMin, trackMax );
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
|
||||
void Session::_doRemovalEvents ()
|
||||
{
|
||||
set<Track*> packTracks;
|
||||
|
|
|
@ -308,6 +308,11 @@ namespace Katana {
|
|||
if (_markers[mbegin]->getNet() != cost.getNet()) {
|
||||
cdebug_log(155,0) << "* Mark: @" << DbU::getValueString(_axis) << " " << _markers[mbegin] << endl;
|
||||
cost.incTerminals( _markers[mbegin]->getWeight(this) );
|
||||
|
||||
if ( (_markers[mbegin]->getRefCount() == 1) and (interval.contains(_markers[mbegin]->getSpan())) ) {
|
||||
cdebug_log(155,0) << " Total overlap of a one track terminal: infinite cost." << endl;
|
||||
cost.setInfinite();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,8 +396,11 @@ namespace Katana {
|
|||
if (_segments.empty()) return Interval(_min,_max);
|
||||
|
||||
getBeginIndex( position, begin, state );
|
||||
if ( (state == InsideElement) and (_segments[begin]->getNet() != net) )
|
||||
if ( (state == InsideElement) and (_segments[begin]->getNet() != net) ) {
|
||||
cdebug_log(155,0) << "Track::getFreeInterval(): Inside other element @" << begin
|
||||
<< " - " << _segments[begin] << endl;
|
||||
return Interval();
|
||||
}
|
||||
|
||||
end = begin;
|
||||
return expandFreeInterval( begin, end, state, net );
|
||||
|
@ -616,7 +624,6 @@ namespace Katana {
|
|||
return free;
|
||||
}
|
||||
|
||||
|
||||
Interval occupied = getOccupiedInterval( index );
|
||||
cdebug_log(155,0) << "Previous occupied:" << occupied << endl;
|
||||
Interval free = getFreeInterval( occupied.getVMin()-1, net );
|
||||
|
@ -642,10 +649,10 @@ namespace Katana {
|
|||
while ( --i != npos ) {
|
||||
if (_segments[i]->getNet() != owner) break;
|
||||
|
||||
cdebug_log(155,0) << "| merge:" << _segments[i] << endl;
|
||||
|
||||
_segments[i]->getCanonical ( segmentInterval );
|
||||
if (segmentInterval.getVMax() >= mergedInterval.getVMin()) {
|
||||
cdebug_log(155,0) << "| merge (prev):" << _segments[i] << endl;
|
||||
|
||||
mergedInterval.merge( segmentInterval );
|
||||
begin = i;
|
||||
}
|
||||
|
@ -658,6 +665,8 @@ namespace Katana {
|
|||
_segments[i]->getCanonical( segmentInterval );
|
||||
if (segmentInterval.getVMin() > mergedInterval.getVMax()) break;
|
||||
|
||||
cdebug_log(155,0) << "| merge (next):" << _segments[i] << endl;
|
||||
|
||||
mergedInterval.merge( segmentInterval );
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ namespace Katana {
|
|||
, _selectFlags (NoFlags)
|
||||
, _selectIndex (0)
|
||||
{
|
||||
cdebug_log(159,1) << "TrackCost::TrackCost() - " << refSegment << endl;
|
||||
cdebug_log(159,0) << " interval1: " << _interval1 << endl;
|
||||
|
||||
std::get<0>( _tracks[0] ) = refTrack;
|
||||
_segment1->addOverlapCost( *this );
|
||||
|
||||
|
@ -68,6 +71,7 @@ namespace Katana {
|
|||
}
|
||||
|
||||
consolidate();
|
||||
cdebug_tabw(159,-1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ namespace Katana {
|
|||
// Wrapped AutoSegment Functions.
|
||||
AutoSegment* TrackElement::base () const { return NULL; }
|
||||
bool TrackElement::isFixed () const { return false; }
|
||||
bool TrackElement::isFixedAxis () const { return false; }
|
||||
bool TrackElement::isLocal () const { return true; }
|
||||
bool TrackElement::isGlobal () const { return not isLocal(); }
|
||||
bool TrackElement::isBipoint () const { return false; }
|
||||
|
@ -162,7 +163,7 @@ namespace Katana {
|
|||
uint32_t TrackElement::getTrackCount () const { return 0; }
|
||||
DbU::Unit TrackElement::getPitch () const { return 0; }
|
||||
DbU::Unit TrackElement::getPPitch () const { return 0; }
|
||||
DbU::Unit TrackElement::getExtensionCap () const { return 0; }
|
||||
DbU::Unit TrackElement::getExtensionCap ( Flags ) const { return 0; }
|
||||
float TrackElement::getMaxUnderDensity ( Flags ) const { return 0.0; };
|
||||
uint32_t TrackElement::getDoglegLevel () const { return 0; }
|
||||
TrackElement* TrackElement::getParent () const { return NULL; }
|
||||
|
|
|
@ -144,6 +144,30 @@ namespace Katana {
|
|||
size_t TrackFixedSegment::getTrackSpan () const { return 1; }
|
||||
|
||||
|
||||
DbU::Unit TrackFixedSegment::getSourceAxis () const
|
||||
{
|
||||
const Horizontal* horizontal = dynamic_cast<const Horizontal*>( _segment );
|
||||
if (horizontal) return horizontal->getSourceX();
|
||||
|
||||
const Vertical* vertical = dynamic_cast<const Vertical*>( _segment );
|
||||
if (vertical) return vertical->getSourceY();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit TrackFixedSegment::getTargetAxis () const
|
||||
{
|
||||
const Horizontal* horizontal = dynamic_cast<const Horizontal*>( _segment );
|
||||
if (horizontal) return horizontal->getTargetX();
|
||||
|
||||
const Vertical* vertical = dynamic_cast<const Vertical*>( _segment );
|
||||
if (vertical) return vertical->getTargetY();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned long TrackFixedSegment::getId () const
|
||||
{
|
||||
cerr << Error("::getId() called on %s.",_getString().c_str()) << endl;
|
||||
|
|
|
@ -81,9 +81,9 @@ namespace Katana {
|
|||
}
|
||||
|
||||
if ( rpDirection xor (uint64_t)rg->getLayerDirection(rg->getLayerDepth(pad->getLayer())) ) {
|
||||
_weight = (uint32_t)(( pitch / (pitch+DbU::toLambda(trackSpan.getSize())) ) * 100.0) ;
|
||||
_weight = (uint32_t)(( pitch / (pitch+trackSpan.getSize()) ) * 100.0) ;
|
||||
} else {
|
||||
_weight = (uint32_t)( (pitch + DbU::toLambda(trackSpan.getSize())) * 20.0 );
|
||||
_weight = (uint32_t)( (pitch + trackSpan.getSize()) * 20.0 );
|
||||
}
|
||||
|
||||
Track* track = rp->getTrackByPosition ( trackSpan.getVMin() );
|
||||
|
|
|
@ -154,6 +154,7 @@ namespace Katana {
|
|||
AutoSegment* TrackSegment::base () const { return _base; }
|
||||
Segment* TrackSegment::getSegment () const { return _base->base(); }
|
||||
bool TrackSegment::isFixed () const { return _base->isFixed(); }
|
||||
bool TrackSegment::isFixedAxis () const { return _base->isFixedAxis(); }
|
||||
bool TrackSegment::isHorizontal () const { return _base->isHorizontal(); }
|
||||
bool TrackSegment::isVertical () const { return _base->isVertical(); }
|
||||
bool TrackSegment::isLocal () const { return not _base->isWeakGlobal() and not _base->isGlobal(); }
|
||||
|
@ -181,7 +182,7 @@ namespace Katana {
|
|||
const Layer* TrackSegment::getLayer () const { return _base->getLayer(); }
|
||||
DbU::Unit TrackSegment::getPitch () const { return _base->getPitch(); }
|
||||
DbU::Unit TrackSegment::getPPitch () const { return _ppitch; }
|
||||
DbU::Unit TrackSegment::getExtensionCap () const { return _base->getExtensionCap(); }
|
||||
DbU::Unit TrackSegment::getExtensionCap ( Flags flags ) const { return _base->getExtensionCap(flags); }
|
||||
DbU::Unit TrackSegment::getAxis () const { return _base->getAxis(); }
|
||||
unsigned long TrackSegment::getFreedomDegree () const { return _freedomDegree; }
|
||||
float TrackSegment::getPriority () const { return _priority; }
|
||||
|
@ -195,6 +196,24 @@ namespace Katana {
|
|||
void TrackSegment::invalidate () { setFlags( TElemInvalidated ); _base->invalidate(); }
|
||||
|
||||
|
||||
DbU::Unit TrackSegment::getSourceAxis () const
|
||||
{
|
||||
DbU::Unit sourceAxis = 0;
|
||||
DbU::Unit targetAxis = 0;
|
||||
base()->getEndAxes( sourceAxis, targetAxis );
|
||||
return sourceAxis;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit TrackSegment::getTargetAxis () const
|
||||
{
|
||||
DbU::Unit sourceAxis = 0;
|
||||
DbU::Unit targetAxis = 0;
|
||||
base()->getEndAxes( sourceAxis, targetAxis );
|
||||
return targetAxis;
|
||||
}
|
||||
|
||||
|
||||
DataNegociate* TrackSegment::getDataNegociate ( Flags flags ) const
|
||||
{
|
||||
if (flags & Flags::DataSelf) return _data;
|
||||
|
|
|
@ -52,4 +52,7 @@ namespace Katana {
|
|||
|
||||
} // Katana namespace.
|
||||
|
||||
|
||||
INSPECTOR_PV_SUPPORT(Katana::Flags)
|
||||
|
||||
#endif // KATANA_CONSTANTS_H
|
||||
|
|
|
@ -58,8 +58,9 @@ namespace Katana {
|
|||
, LocalVsGlobal = 7
|
||||
, MoveUp = 8
|
||||
, MaximumSlack = 9
|
||||
, Unimplemented =10
|
||||
, Repair =11
|
||||
, Unimplemented = 10
|
||||
, Repair = 11
|
||||
, RepairFailed = 12
|
||||
};
|
||||
public:
|
||||
DataNegociate ( TrackElement* );
|
||||
|
@ -89,6 +90,7 @@ namespace Katana {
|
|||
inline void resetRipupCount ();
|
||||
inline void resetStateCount ();
|
||||
void update ();
|
||||
static string getStateString ( uint32_t state, unsigned int stateCount );
|
||||
static string getStateString ( DataNegociate* );
|
||||
Record* _getRecord () const;
|
||||
string _getString () const;
|
||||
|
@ -141,6 +143,18 @@ namespace Katana {
|
|||
|
||||
inline void DataNegociate::setState ( uint32_t state, Flags flags )
|
||||
{
|
||||
if ( (_state >= Repair) and (state < _state) ) {
|
||||
std::cerr << "Revert DataNegociate state from Repair/RepairFailed to " << getStateString(state,_stateCount).c_str() << std::endl;
|
||||
std::cerr << "On " << _getString() << std::endl;
|
||||
|
||||
std::cerr << *((char*)NULL) << std::endl;
|
||||
|
||||
throw Hurricane::Error( "Revert DataNegociate state from Repair/RepairFailed to %s."
|
||||
" On %s"
|
||||
, getStateString(state,_stateCount).c_str()
|
||||
, _getString().c_str()
|
||||
);
|
||||
}
|
||||
if ( (_state != state) or (flags & Flags::ResetCount) ) {
|
||||
//std::cerr << "Changing state to:" << state << std::endl;
|
||||
_state = state;
|
||||
|
@ -155,4 +169,7 @@ namespace Katana {
|
|||
|
||||
} // Katana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Katana::DataNegociate);
|
||||
|
||||
#endif // KATANA_DATA_NEGOCIATE_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2013, All Rights Reserved
|
||||
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
|
@ -22,6 +22,7 @@
|
|||
|
||||
namespace Katana {
|
||||
|
||||
class TrackElement;
|
||||
class RoutingEvent;
|
||||
|
||||
|
||||
|
@ -33,9 +34,10 @@ namespace Katana {
|
|||
public:
|
||||
class Element {
|
||||
public:
|
||||
inline Element ( size_t id=0, size_t timestamp=0 );
|
||||
inline Element ( TrackElement* segment, size_t timestamp=0 );
|
||||
size_t getId () const;
|
||||
public:
|
||||
size_t _id;
|
||||
TrackElement* _segment;
|
||||
size_t _timestamp;
|
||||
int _count;
|
||||
};
|
||||
|
@ -48,8 +50,8 @@ namespace Katana {
|
|||
inline bool isLooping () const;
|
||||
inline int getMaxCount () const;
|
||||
inline const std::vector<Element>& getElements () const;
|
||||
void update ( size_t id );
|
||||
void erase ( size_t id );
|
||||
void update ( TrackElement* );
|
||||
void erase ( TrackElement* );
|
||||
private:
|
||||
std::vector<Element> _elements;
|
||||
size_t _depth;
|
||||
|
@ -59,8 +61,8 @@ namespace Katana {
|
|||
};
|
||||
|
||||
|
||||
inline RoutingEventLoop::Element::Element ( size_t id, size_t timestamp )
|
||||
: _id(id), _timestamp(timestamp), _count(1)
|
||||
inline RoutingEventLoop::Element::Element ( TrackElement* segment, size_t timestamp )
|
||||
: _segment(segment), _timestamp(timestamp), _count(1)
|
||||
{ }
|
||||
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ namespace Katana {
|
|||
~SegmentFsm ();
|
||||
inline bool isFullBlocked () const;
|
||||
inline bool isSymmetric () const;
|
||||
inline bool isMinimizeDrag () const;
|
||||
inline RoutingEvent* getEvent () const;
|
||||
inline RoutingEvent* getEvent1 () const;
|
||||
inline RoutingEvent* getEvent2 () const;
|
||||
|
@ -187,9 +188,11 @@ namespace Katana {
|
|||
bool _fullBlocked;
|
||||
bool _sameAxis;
|
||||
bool _useEvent2;
|
||||
bool _minimizeDrag;
|
||||
};
|
||||
|
||||
|
||||
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; }
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace Katana {
|
|||
using Hurricane::Contact;
|
||||
using Hurricane::Segment;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Interval;
|
||||
using Anabatic::AutoContact;
|
||||
using Anabatic::AutoSegment;
|
||||
|
||||
|
@ -74,6 +75,7 @@ namespace Katana {
|
|||
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* );
|
||||
|
@ -90,6 +92,7 @@ namespace Katana {
|
|||
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 ();
|
||||
|
@ -164,6 +167,9 @@ namespace Katana {
|
|||
inline Anabatic::GCell* Session::getGCellUnder ( DbU::Unit x, DbU::Unit y )
|
||||
{ return get("getGCellUnder()")->_getGCellUnder(x,y); }
|
||||
|
||||
inline Interval& Session::toAxisInterval ( Interval& interval, size_t depth )
|
||||
{ return get("getGCellUnder()")->_toAxisInterval(interval,depth); }
|
||||
|
||||
inline void Session::addInsertEvent ( TrackMarker* marker, Track* track )
|
||||
{ get("addInsertEvent(TrackMarker*)")->_addInsertEvent(marker,track); }
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace Katana {
|
|||
virtual Segment* getSegment () const = 0;
|
||||
// Wrapped AutoSegment Functions (when applicable).
|
||||
virtual bool isFixed () const;
|
||||
virtual bool isFixedAxis () const;
|
||||
virtual bool isHorizontal () const = 0;
|
||||
virtual bool isVertical () const = 0;
|
||||
virtual bool isWide () const;
|
||||
|
@ -151,11 +152,13 @@ namespace Katana {
|
|||
inline Box getBoundingBox () const;
|
||||
virtual TrackElement* getNext () const;
|
||||
virtual TrackElement* getPrevious () const;
|
||||
virtual DbU::Unit getExtensionCap () const;
|
||||
virtual DbU::Unit getExtensionCap ( Flags ) const;
|
||||
virtual DbU::Unit getAxis () const = 0;
|
||||
inline DbU::Unit getSymmetricAxis ( DbU::Unit ) const;
|
||||
inline DbU::Unit getSourceU () const;
|
||||
inline DbU::Unit getTargetU () const;
|
||||
virtual DbU::Unit getSourceAxis () const = 0;
|
||||
virtual DbU::Unit getTargetAxis () const = 0;
|
||||
inline DbU::Unit getLength () const;
|
||||
inline Interval getCanonicalInterval () const;
|
||||
virtual Interval getFreeInterval () const;
|
||||
|
|
|
@ -55,6 +55,8 @@ namespace Katana {
|
|||
virtual TrackElement* getNext () const;
|
||||
virtual TrackElement* getPrevious () const;
|
||||
virtual DbU::Unit getAxis () const;
|
||||
inline DbU::Unit getSourceAxis () const;
|
||||
virtual DbU::Unit getTargetAxis () const;
|
||||
virtual Interval getFreeInterval () const;
|
||||
virtual void addOverlapCost ( TrackCost& ) const;
|
||||
virtual float getPriority () const;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2008-2013, All Rights Reserved
|
||||
// Copyright (c) UPMC 2008-2018, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
|
@ -31,6 +31,7 @@ namespace Katana {
|
|||
|
||||
using Hurricane::Record;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Interval;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Net;
|
||||
|
||||
|
@ -47,8 +48,10 @@ namespace Katana {
|
|||
void destroy ();
|
||||
public:
|
||||
Net* getNet () const;
|
||||
inline uint32_t getRefCount () const;
|
||||
inline DbU::Unit getSourceU () const;
|
||||
inline DbU::Unit getTargetU () const;
|
||||
inline Interval getSpan () const;
|
||||
inline Track* getTrack () const;
|
||||
inline uint32_t getWeight ( const Track* ) const;
|
||||
inline void setTrack ( Track* );
|
||||
|
@ -85,8 +88,10 @@ namespace Katana {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline uint32_t TrackMarker::getRefCount () const { return _refcount; }
|
||||
inline DbU::Unit TrackMarker::getSourceU () const { return _sourcePosition; }
|
||||
inline DbU::Unit TrackMarker::getTargetU () const { return _targetPosition; }
|
||||
inline Interval TrackMarker::getSpan () const { return Interval(_sourcePosition,_targetPosition); }
|
||||
inline Track* TrackMarker::getTrack () const { return _track; }
|
||||
inline uint32_t TrackMarker::getWeight ( const Track* track ) const { return _weight; }
|
||||
inline void TrackMarker::setTrack ( Track* track ) { _track = track; }
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace Katana {
|
|||
virtual AutoSegment* base () const;
|
||||
virtual Segment* getSegment () const;
|
||||
virtual bool isFixed () const;
|
||||
virtual bool isFixedAxis () const;
|
||||
virtual bool isHorizontal () const;
|
||||
virtual bool isVertical () const;
|
||||
virtual bool isLocal () const;
|
||||
|
@ -85,11 +86,11 @@ namespace Katana {
|
|||
virtual bool canDogleg ();
|
||||
virtual bool canDogleg ( Interval );
|
||||
virtual bool canDogleg ( Anabatic::GCell*, Flags flags=0 );
|
||||
virtual bool canPivotUp ( float reserve, Flags flags ) const;
|
||||
virtual bool canPivotDown ( float reserve, Flags flags ) const;
|
||||
virtual bool canMoveUp ( float reserve, Flags flags ) const;
|
||||
virtual bool canPivotUp ( float reserve, Flags ) const;
|
||||
virtual bool canPivotDown ( float reserve, Flags ) const;
|
||||
virtual bool canMoveUp ( float reserve, Flags ) const;
|
||||
virtual bool canSlacken () const;
|
||||
virtual float getMaxUnderDensity ( Flags flags ) const;
|
||||
virtual float getMaxUnderDensity ( Flags ) const;
|
||||
virtual unsigned long getId () const;
|
||||
virtual Flags getDirection () const;
|
||||
virtual Net* getNet () const;
|
||||
|
@ -97,7 +98,7 @@ namespace Katana {
|
|||
virtual const Layer* getLayer () const;
|
||||
virtual DbU::Unit getPitch () const;
|
||||
virtual DbU::Unit getPPitch () const;
|
||||
virtual DbU::Unit getExtensionCap () const;
|
||||
virtual DbU::Unit getExtensionCap ( Flags ) const;
|
||||
virtual unsigned long getFreedomDegree () const;
|
||||
virtual float getPriority () const;
|
||||
virtual uint32_t getDoglegLevel () const;
|
||||
|
@ -105,6 +106,8 @@ namespace Katana {
|
|||
virtual TrackElement* getPrevious () const;
|
||||
virtual TrackElement* getParent () const;
|
||||
virtual DbU::Unit getAxis () const;
|
||||
virtual DbU::Unit getSourceAxis () const;
|
||||
virtual DbU::Unit getTargetAxis () const;
|
||||
virtual Interval getFreeInterval () const;
|
||||
virtual Interval getSourceConstraints () const;
|
||||
virtual Interval getTargetConstraints () const;
|
||||
|
@ -137,10 +140,10 @@ namespace Katana {
|
|||
virtual TrackElement* makeDogleg ( Anabatic::GCell*, TrackElement*& perpandicular, TrackElement*& parallel );
|
||||
virtual TrackElement* makeDogleg ( Interval, Flags& flags );
|
||||
virtual void _postDoglegs ( TrackElement*& perpandicular, TrackElement*& parallel );
|
||||
virtual bool moveAside ( Flags flags );
|
||||
virtual bool moveAside ( Flags );
|
||||
virtual bool slacken ( Flags flags=Flags::NoFlags );
|
||||
virtual bool moveUp ( Flags flags );
|
||||
virtual bool moveDown ( Flags flags );
|
||||
virtual bool moveUp ( Flags );
|
||||
virtual bool moveDown ( Flags );
|
||||
#if THIS_IS_DISABLED
|
||||
virtual void desalignate ();
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue