573 lines
17 KiB
C++
573 lines
17 KiB
C++
|
|
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
|
//
|
|
// ===================================================================
|
|
//
|
|
// $Id$
|
|
//
|
|
// x-----------------------------------------------------------------x
|
|
// | |
|
|
// | C O R I O L I S |
|
|
// | K i t e - D e t a i l e d R o u t e r |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./GCell.cpp" |
|
|
// | *************************************************************** |
|
|
// | U p d a t e s |
|
|
// | |
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
#include <limits>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
#include "hurricane/Bug.h"
|
|
#include "hurricane/Error.h"
|
|
#include "hurricane/Warning.h"
|
|
#include "hurricane/Component.h"
|
|
#include "hurricane/RoutingPad.h"
|
|
#include "katabatic/AutoSegment.h"
|
|
#include "katabatic/AutoContact.h"
|
|
#include "kite/DataNegociate.h"
|
|
#include "kite/TrackSegment.h"
|
|
#include "kite/RoutingPlane.h"
|
|
#include "kite/GCell.h"
|
|
#include "kite/GCellGrid.h"
|
|
#include "kite/NegociateWindow.h"
|
|
|
|
|
|
namespace {
|
|
|
|
using namespace Hurricane;
|
|
using namespace Kite;
|
|
|
|
|
|
TrackElement* getCandidate ( RoutingPad* rp, Box bb )
|
|
{
|
|
size_t depth = Session::getConfiguration()->getLayerDepth ( rp->getLayer() );
|
|
if ( depth > 2 ) return NULL;
|
|
|
|
DebugSession::open ( rp->getNet(), 200 );
|
|
|
|
//if ( (depth != 0) and (depth != 2) ) return NULL;
|
|
|
|
ltrace(200) << "depth: " << depth << " " << rp->getSourcePosition() << " " << rp << endl;
|
|
|
|
if ( depth%2 == 0 ) {
|
|
// Propagate from vertical Terminals.
|
|
forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet<Contact*>() ) {
|
|
if ( not bb.contains(icontact->getCenter()) ) continue;
|
|
|
|
forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet<Segment*>() ) {
|
|
TrackElement* autoSegment = Session::lookup(*isegment);
|
|
if ( not autoSegment or autoSegment->isFixed() ) continue;
|
|
|
|
DebugSession::close ();
|
|
return autoSegment;
|
|
}
|
|
}
|
|
} else {
|
|
#if DISABLED
|
|
// Propage from Horizontal Terminals.
|
|
bool hasM3protect = false;
|
|
AutoContact* toContact = NULL;
|
|
|
|
forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet<Contact*>() ) {
|
|
if ( not bb.contains(icontact->getCenter()) ) continue;
|
|
|
|
forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet<Segment*>() ) {
|
|
TrackElement* autoSegment = Session::lookup(*isegment);
|
|
if ( not autoSegment ) continue;
|
|
if ( autoSegment->isFixed() ) {
|
|
if ( Session::getConfiguration()->getLayerDepth(autoSegment->getLayer()) == 2 ) {
|
|
ltrace(200) << "M3 protection found for " << rp << endl;
|
|
hasM3protect = true;
|
|
}
|
|
continue;
|
|
}
|
|
toContact = autoSegment->base()->getAutoSource();
|
|
if ( toContact->base() == *icontact )
|
|
toContact = autoSegment->base()->getAutoTarget();
|
|
}
|
|
}
|
|
|
|
// Find M3 associated to this terminal.
|
|
if ( hasM3protect ) {
|
|
if ( toContact ) {
|
|
ltrace(200) << "toContact: " << toContact << endl;
|
|
forEach ( Segment*, isegment, toContact->base()->getSlaveComponents().getSubSet<Segment*>() ) {
|
|
ltrace(200) << "| slave: " << *isegment << endl;
|
|
if ( Session::getConfiguration()->getLayerDepth(isegment->getLayer()) == 2 ) {
|
|
TrackElement* autoSegment = Session::lookup(*isegment);
|
|
ltrace(200) << "M3 candidate: " << autoSegment << endl;
|
|
DebugSession::close ();
|
|
return autoSegment;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DebugSession::close ();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
namespace Kite {
|
|
|
|
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::swap;
|
|
using std::numeric_limits;
|
|
using Hurricane::tab;
|
|
using Hurricane::inltrace;
|
|
using Hurricane::ltracein;
|
|
using Hurricane::ltraceout;
|
|
using Hurricane::roundfp;
|
|
using Hurricane::Bug;
|
|
using Hurricane::Error;
|
|
using Hurricane::Warning;
|
|
using Hurricane::ForEachIterator;
|
|
using Hurricane::Component;
|
|
using Hurricane::RoutingPad;
|
|
|
|
using Katabatic::AutoContact;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Kite::GCell::CompareByDensity".
|
|
//
|
|
// lhs < rhs --> true
|
|
|
|
|
|
bool GCell::CompareByDensity::operator() ( GCell* lhs, GCell* rhs )
|
|
{
|
|
//int difference = floatCompare ( lhs->base()->getDensity(), rhs->base()->getDensity() );
|
|
//if ( abs(difference) > 1000 ) return difference > 0;
|
|
|
|
float difference = roundfp ( lhs->base()->getDensity() - rhs->base()->getDensity() );
|
|
if ( difference != 0.0 ) return (difference > 0.0);
|
|
|
|
if ( lhs->getIndex() < rhs->getIndex() ) return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Kite::GCell::CompareByStiffness".
|
|
//
|
|
// lhs < rhs --> true
|
|
|
|
|
|
bool GCell::CompareByStiffness::operator() ( GCell* lhs, GCell* rhs )
|
|
{
|
|
if ( lhs->isRouted() xor rhs->isRouted() ) return rhs->isRouted();
|
|
|
|
float difference = roundfp ( lhs->getStiffness() - rhs->getStiffness() );
|
|
if ( difference != 0.0 ) return (difference > 0.0);
|
|
|
|
return lhs->getIndex() < rhs->getIndex();
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Kite::GCell".
|
|
|
|
|
|
GCell::GCell ( GCellGrid* grid, Katabatic::GCell* gcell )
|
|
: _gcellGrid (grid)
|
|
, _base (gcell)
|
|
, _segments ()
|
|
, _order (numeric_limits<unsigned int>::max())
|
|
, _isInRoutingSet (false)
|
|
, _isRouted (false)
|
|
{
|
|
if ( !gcell )
|
|
cerr << Bug("GCell:GCell() - NULL base.") << endl;
|
|
|
|
_leftSegments [0] = NULL;
|
|
_leftSegments [1] = NULL;
|
|
_rightSegments[0] = NULL;
|
|
_rightSegments[1] = NULL;
|
|
}
|
|
|
|
|
|
GCell* GCell::create ( GCellGrid* grid, Katabatic::GCell* gcell )
|
|
{
|
|
GCell* kiteGCell = new GCell ( grid, gcell );
|
|
|
|
ltrace(90) << "Kite::GCell::create() - " << (void*)kiteGCell << " " << kiteGCell << endl;
|
|
|
|
return kiteGCell;
|
|
}
|
|
|
|
|
|
GCell::~GCell ()
|
|
{ }
|
|
|
|
|
|
void GCell::destroy ()
|
|
{
|
|
ltrace(90) << "Kite::GCell::destroy() - " << (void*)this << " " << this << endl;
|
|
ltracein(90);
|
|
|
|
for ( size_t i=0 ; i < _segments.size() ; i++ ) {
|
|
if ( !_segments[i]->getTrack() )
|
|
_segments[i]->destroy ();
|
|
else {
|
|
cerr << Error("%s still bound to a track!\n"
|
|
" (not deleted: let's get the memory leak)"
|
|
,getString(_segments[i]).c_str()
|
|
) << endl;
|
|
}
|
|
}
|
|
delete this;
|
|
|
|
ltraceout(90);
|
|
}
|
|
|
|
|
|
GCell* GCell::getLeft () const
|
|
{
|
|
return _gcellGrid->getGCellLeft(this);
|
|
}
|
|
|
|
|
|
GCell* GCell::getRight () const
|
|
{
|
|
return _gcellGrid->getGCellRight(this);
|
|
}
|
|
|
|
|
|
GCell* GCell::getUp () const
|
|
{
|
|
return _gcellGrid->getGCellUp(this);
|
|
}
|
|
|
|
|
|
GCell* GCell::getDown () const
|
|
{
|
|
return _gcellGrid->getGCellDown(this);
|
|
}
|
|
|
|
|
|
bool GCell::areDensityConnex ( GCell* a, GCell* b )
|
|
{ return Katabatic::GCell::areDensityConnex ( a->base(), b->base() ); }
|
|
|
|
|
|
GCell* GCell::getLowestOrder ( TrackElement* trackSegment )
|
|
{
|
|
vector<GCell*> gcells;
|
|
trackSegment->getGCells ( gcells );
|
|
|
|
if ( gcells.empty() ) return NULL;
|
|
|
|
size_t ilower = 0;
|
|
for ( size_t i=0 ; i<gcells.size() ; i++ )
|
|
if ( gcells[i]->getOrder() < gcells[ilower]->getOrder() )
|
|
ilower = i;
|
|
|
|
return gcells[ilower];
|
|
}
|
|
|
|
|
|
void GCell::loadRouting ( unsigned int order )
|
|
{
|
|
_segments.clear ();
|
|
_order = order;
|
|
|
|
ltrace(200) << "GCell::loadRouting() - " << this << " Session:" << Session::getOrder() << endl;
|
|
ltracein(200);
|
|
|
|
Segment* segment;
|
|
AutoSegment* autoSegment;
|
|
|
|
ltrace(149) << "AutoSegments from AutoContacts" << endl;
|
|
vector<AutoContact*>* contacts = getContacts();
|
|
for ( size_t i=0 ; i<contacts->size() ; i++ ) {
|
|
forEach ( Component*, component, (*contacts)[i]->getSlaveComponents() ) {
|
|
segment = dynamic_cast<Segment*>(*component);
|
|
autoSegment = Session::base()->lookup ( segment );
|
|
ltrace(149) << autoSegment << endl;
|
|
if ( autoSegment ) {
|
|
addTrackSegment ( this, autoSegment, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
// // Effective deletion of rejecteds.
|
|
// set<AutoSegment*>::iterator ireject = rejecteds.begin();
|
|
// for ( ; ireject != rejecteds.end() ; ireject++ ) {
|
|
// }
|
|
|
|
ltrace(149) << "Horizontal overcell AutoSegments" << endl;
|
|
vector<AutoSegment*>* segments = getHSegments();
|
|
for ( size_t i=0 ; i<segments->size() ; i++ ) {
|
|
addTrackSegment ( this, (*segments)[i], true );
|
|
}
|
|
|
|
ltrace(149) << "Vertical overcell AutoSegments" << endl;
|
|
segments = getVSegments();
|
|
for ( size_t i=0 ; i<segments->size() ; i++ ) {
|
|
addTrackSegment ( this, (*segments)[i], true );
|
|
}
|
|
|
|
ltrace(149) << "_segments.size():" << _segments.size() << endl;
|
|
ltraceout(200);
|
|
}
|
|
|
|
|
|
void GCell::computeBorder ()
|
|
{
|
|
ltrace(200) << "GCell::computeBorder() " << this << endl;
|
|
ltracein(200);
|
|
|
|
vector<AutoContact*>* contacts = _base->getContacts();
|
|
TrackElement* candidate;
|
|
DataNegociate* data;
|
|
Box bb = getBoundingBox();
|
|
size_t iLeft = 0;
|
|
size_t iRight = 0;
|
|
|
|
for ( size_t icontact=0 ; icontact < contacts->size() ; icontact++ ) {
|
|
Component* anchor = (*contacts)[icontact]->getAnchor();
|
|
RoutingPad* rp = dynamic_cast<RoutingPad*>(anchor);
|
|
|
|
if ( not rp ) continue;
|
|
|
|
// size_t depth = Session::getConfiguration()->getLayerDepth ( rp->getLayer() );
|
|
// if ( (depth != 0) and (depth != 2) ) continue;
|
|
|
|
// ltrace(200) << "depth: " << depth << " " << rp << endl;
|
|
|
|
candidate = getCandidate ( rp, bb );
|
|
if ( not candidate ) continue;
|
|
|
|
data = candidate->getDataNegociate();
|
|
if ( not data ) continue;
|
|
|
|
// Ugly: hardwired pitch usage.
|
|
if ( (rp->getX() - getX() < DbU::lambda(11.0)) and (iLeft < 2) ) {
|
|
//data->setLeftBorder(true);
|
|
ltrace(200) << "Left Segments[" << iLeft << "]: " << candidate << endl;
|
|
_leftSegments[iLeft++] = candidate;
|
|
continue;
|
|
}
|
|
|
|
if ( (getXMax() - rp->getX() < DbU::lambda(11.0)) and (iRight < 2) ) {
|
|
//data->setRightBorder(true);
|
|
ltrace(200) << "Right Segment[" << iRight << "]: " << candidate << endl;
|
|
_rightSegments[iRight++] = candidate;
|
|
}
|
|
}
|
|
|
|
ltraceout(200);
|
|
}
|
|
|
|
|
|
TrackElement* GCell::addTrackSegment ( GCell* gcell, AutoSegment* autoSegment, bool loading )
|
|
{
|
|
ltrace(200) << "GCell::addTrackSegment() - " << autoSegment << endl;
|
|
ltracein(159);
|
|
|
|
// Special case: fixed AutoSegments must not interfere with blockages.
|
|
// Ugly: uses of getExtensionCap().
|
|
if ( autoSegment->isFixed() ) {
|
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
|
|
Track* track = plane->getTrackByPosition ( autoSegment->getAxis() );
|
|
size_t begin;
|
|
size_t end;
|
|
Interval fixedSpan;
|
|
Interval blockageSpan;
|
|
|
|
autoSegment->getCanonical ( fixedSpan );
|
|
fixedSpan.inflate ( Session::getExtensionCap()-1 );
|
|
|
|
track->getOverlapBounds ( fixedSpan, begin, end );
|
|
for ( ; (begin < end) ; begin++ ) {
|
|
|
|
TrackElement* other = track->getSegment(begin);
|
|
ltrace(200) << "| overlap: " << other << endl;
|
|
|
|
if ( not other->isBlockage() ) continue;
|
|
|
|
other->getCanonical ( blockageSpan );
|
|
blockageSpan.inflate(Session::getExtensionCap());
|
|
|
|
ltrace(200) << " fixed:" << fixedSpan << " vs. blockage:" << blockageSpan << endl;
|
|
|
|
if ( not fixedSpan.intersect(blockageSpan) ) continue;
|
|
|
|
// Overlap between fixed & blockage.
|
|
ltrace(200) << "* Blockage overlap: " << autoSegment << endl;
|
|
Session::destroyRequest ( autoSegment );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
Interval span;
|
|
autoSegment = autoSegment->getCanonical ( span );
|
|
|
|
bool created;
|
|
TrackElement* trackSegment = TrackSegment::create ( autoSegment, NULL, created );
|
|
DataNegociate* data = trackSegment->getDataNegociate ();
|
|
GCell* previousGCell = trackSegment->getGCell();
|
|
|
|
if ( not loading )
|
|
ltrace(159) << "* lookup: " << autoSegment << endl;
|
|
|
|
if ( created )
|
|
ltrace(159) << "* " << trackSegment << endl;
|
|
|
|
if ( not created and not loading ) {
|
|
ltrace(200) << "TrackSegment already exists (and not in loading stage)." << endl;
|
|
ltrace(200) << "Previous owning GCell: " << previousGCell << endl;
|
|
if ( previousGCell != gcell ) {
|
|
previousGCell->removeTrackSegment ( trackSegment );
|
|
trackSegment->setGCell ( NULL );
|
|
}
|
|
}
|
|
|
|
vector<GCell*> gcells;
|
|
trackSegment->getGCells ( gcells );
|
|
GCell* lowest = gcells[0];
|
|
bool validPrevious = false;
|
|
|
|
for ( size_t igcell=0 ; igcell<gcells.size() ; igcell++ ) {
|
|
ltrace(200) << "| " << igcell << ":" << gcells[igcell] << endl;
|
|
if ( gcells[igcell]->getOrder() < lowest->getOrder()) {
|
|
lowest = gcells[igcell];
|
|
}
|
|
if ( gcells[igcell] == previousGCell ) validPrevious = true;
|
|
}
|
|
if ( not validPrevious ) previousGCell = NULL;
|
|
|
|
if ( not gcell ) {
|
|
gcell = lowest;
|
|
if ( previousGCell and (gcell->getOrder() == previousGCell->getOrder()) )
|
|
gcell = previousGCell;
|
|
ltrace(200) << "New owner: " << gcell << endl;
|
|
} else if ( created ) {
|
|
if ( (lowest != gcell) && (lowest->getOrder() != gcell->getOrder() ) ) {
|
|
cerr << Bug("Not the right lowest: %s",getString(lowest).c_str()) << endl;
|
|
}
|
|
}
|
|
|
|
if ( (gcell->getOrder() > Session::getOrder()) and not (data->isRing() or data->isBorder()) ) {
|
|
cinfo << "[INFO] GCell::addTrackSegment() - Owning GCell is not in active set ("
|
|
<< gcell->getOrder() << " > Session:" << Session::getOrder() << ")."
|
|
<< "\n " << trackSegment
|
|
<< endl;
|
|
}
|
|
|
|
if ( not trackSegment->getGCell() ) {
|
|
trackSegment->setGCell ( gcell );
|
|
gcell->addTrackSegment ( trackSegment );
|
|
|
|
if ( loading ) {
|
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(autoSegment->getLayer());
|
|
Track* track = plane->getTrackByPosition ( autoSegment->getAxis() );
|
|
Interval uside = gcell->getUSide ( Constant::perpandicular(autoSegment->getDirection()), false );
|
|
|
|
if ( track->getAxis() > uside.getVMax() ) track = track->getPrevious();
|
|
if ( track->getAxis() < uside.getVMin() ) track = track->getNext();
|
|
|
|
trackSegment->setAxis ( track->getAxis(), Katabatic::Realignate|Katabatic::AxisSet );
|
|
trackSegment->invalidate ();
|
|
|
|
if ( created and trackSegment->isFixed() ) {
|
|
Session::addInsertEvent ( trackSegment, track );
|
|
}
|
|
}
|
|
}
|
|
|
|
ltraceout(159);
|
|
|
|
return trackSegment;
|
|
}
|
|
|
|
|
|
void GCell::addTrackSegment ( TrackElement* trackSegment )
|
|
{
|
|
_segments.push_back ( trackSegment );
|
|
}
|
|
|
|
|
|
void GCell::removeTrackSegment ( TrackElement* trackSegment )
|
|
{
|
|
if ( _segments.empty() ) return;
|
|
|
|
size_t i = 0;
|
|
for ( ; i<_segments.size() ; i++ )
|
|
if ( _segments[i] == trackSegment ) {
|
|
swap ( _segments[i], _segments[_segments.size()-1] );
|
|
break;
|
|
}
|
|
|
|
if ( i < _segments.size() ) _segments.pop_back ();
|
|
}
|
|
|
|
|
|
double GCell::getOwnedWireLength () const
|
|
{
|
|
double ownedWL = 0;
|
|
|
|
for ( size_t i=0 ; i<_segments.size() ; i++ ) {
|
|
ownedWL += DbU::getLambda ( _segments[i]->getLength() );
|
|
}
|
|
|
|
return ownedWL;
|
|
}
|
|
|
|
|
|
void GCell::anticipateRouting ( unsigned int order )
|
|
{
|
|
if ( order < _order ) {
|
|
setRouted ( true );
|
|
loadRouting ( order );
|
|
// _order = order;
|
|
// for ( size_t isegment=0 ; isegment<_segments.size() ; ++isegment ) {
|
|
// DataNegociate* data = _segments[isegment]->getDataNegociate();
|
|
// data->setGCellOrder ( order );
|
|
// data->resetBorder ();
|
|
// }
|
|
}
|
|
}
|
|
|
|
|
|
string GCell::_getTypeName() const
|
|
{ return "Kite::GCell"; }
|
|
|
|
|
|
string GCell::_getString () const
|
|
{
|
|
string s = _base->_getString();
|
|
s.erase ( s.size()-1 );
|
|
s += " o:";
|
|
s += ((_order == numeric_limits<unsigned int>::max()) ? "-" : getString(_order));
|
|
s += " ";
|
|
s += ((_isRouted) ? "R" : "-");
|
|
s += ">";
|
|
return s;
|
|
}
|
|
|
|
|
|
Record* GCell::_getRecord () const
|
|
{ return _base->_getRecord(); }
|
|
|
|
|
|
|
|
} // End of Kite namespace.
|