440 lines
14 KiB
C++
440 lines
14 KiB
C++
|
|
||
|
// -*- C++ -*-
|
||
|
//
|
||
|
// This file is part of the Coriolis Software.
|
||
|
// Copyright (c) UPMC/LIP6 2008-2009, 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 : "./QueryBlockages.cpp" |
|
||
|
// | *************************************************************** |
|
||
|
// | U p d a t e s |
|
||
|
// | |
|
||
|
// x-----------------------------------------------------------------x
|
||
|
|
||
|
|
||
|
#include <map>
|
||
|
#include <list>
|
||
|
|
||
|
#include "hurricane/DataBase.h"
|
||
|
#include "hurricane/Technology.h"
|
||
|
#include "hurricane/BasicLayer.h"
|
||
|
#include "hurricane/RegularLayer.h"
|
||
|
#include "hurricane/Query.h"
|
||
|
#include "kite/RoutingPlane.h"
|
||
|
#include "kite/TrackBlockage.h"
|
||
|
#include "kite/Track.h"
|
||
|
#include "kite/KiteEngine.h"
|
||
|
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
using namespace std;
|
||
|
using Hurricane::tab;
|
||
|
using Hurricane::inltrace;
|
||
|
using Hurricane::DbU;
|
||
|
using Hurricane::Box;
|
||
|
using Hurricane::Interval;
|
||
|
using Hurricane::Query;
|
||
|
using Hurricane::Go;
|
||
|
using Hurricane::Rubber;
|
||
|
using Hurricane::Layer;
|
||
|
using Hurricane::BasicLayer;
|
||
|
using Hurricane::RegularLayer;
|
||
|
using Hurricane::Transformation;
|
||
|
using namespace Kite;
|
||
|
|
||
|
|
||
|
// -------------------------------------------------------------------
|
||
|
// Class : "::BlockagesPlanes".
|
||
|
|
||
|
|
||
|
class BlockagesPlanes {
|
||
|
private:
|
||
|
class Track {
|
||
|
public:
|
||
|
Track ( Kite::Track* );
|
||
|
void add ( Interval );
|
||
|
inline DbU::Unit getAxis () const;
|
||
|
void dump ( DbU::Unit width );
|
||
|
private:
|
||
|
Kite::Track* _ktrack;
|
||
|
list<Interval> _blockages;
|
||
|
};
|
||
|
private:
|
||
|
class Plane {
|
||
|
public:
|
||
|
Plane ( RoutingPlane* );
|
||
|
~Plane ();
|
||
|
void merge ( Box boundingBox );
|
||
|
inline unsigned int getDirection () const;
|
||
|
inline const Layer* getLayer () const;
|
||
|
inline DbU::Unit getHalfWireWidth () const;
|
||
|
inline DbU::Unit getPitch () const;
|
||
|
void dump ();
|
||
|
private:
|
||
|
RoutingPlane* _routingPlane;
|
||
|
Interval _axisSpan;
|
||
|
vector<Track*> _tracks;
|
||
|
};
|
||
|
public:
|
||
|
static Track* createTrack ( Kite::Track* );
|
||
|
public:
|
||
|
BlockagesPlanes ( KiteEngine* );
|
||
|
~BlockagesPlanes ();
|
||
|
bool hasPlane ( const BasicLayer* );
|
||
|
bool setActivePlane ( const BasicLayer* );
|
||
|
inline Plane* getActivePlane () const;
|
||
|
void add ( Box boundingBox );
|
||
|
void dump ();
|
||
|
private:
|
||
|
KiteEngine* _kite;
|
||
|
map<const BasicLayer*,Plane*> _planes;
|
||
|
Plane* _activePlane;
|
||
|
};
|
||
|
|
||
|
|
||
|
BlockagesPlanes::Track::Track ( Kite::Track* ktrack )
|
||
|
: _ktrack(ktrack)
|
||
|
, _blockages()
|
||
|
{ }
|
||
|
|
||
|
|
||
|
inline DbU::Unit BlockagesPlanes::Track::getAxis () const { return _ktrack->getAxis(); }
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::Track::add ( Interval obstacle )
|
||
|
{
|
||
|
if ( (obstacle.getVMax() <= _ktrack->getMin())
|
||
|
or (obstacle.getVMin() >= _ktrack->getMax()) ) return;
|
||
|
|
||
|
list<Interval>::iterator imerge = _blockages.end();
|
||
|
list<Interval>::iterator iblockage = _blockages.begin();
|
||
|
|
||
|
while ( iblockage != _blockages.end() ) {
|
||
|
if ( obstacle.getVMax() < (*iblockage).getVMin() ) break;
|
||
|
|
||
|
if ( obstacle.intersect(*iblockage) ) {
|
||
|
if ( imerge == _blockages.end() ) {
|
||
|
imerge = iblockage;
|
||
|
(*imerge).merge ( obstacle );
|
||
|
} else {
|
||
|
(*imerge).merge ( *iblockage );
|
||
|
iblockage = _blockages.erase ( iblockage );
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
iblockage++;
|
||
|
}
|
||
|
|
||
|
if ( imerge == _blockages.end() ) {
|
||
|
_blockages.insert ( iblockage, obstacle );
|
||
|
ltrace(190) << "| Add on " << DbU::getValueString(_ktrack->getAxis()) << " " << obstacle << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::Track::dump ( DbU::Unit width )
|
||
|
{
|
||
|
list<Interval>::iterator iinterval = _blockages.begin();
|
||
|
|
||
|
if ( _ktrack->getDirection() == Constant::Horizontal ) {
|
||
|
DbU::Unit ymin = _ktrack->getAxis() - width/2;
|
||
|
DbU::Unit ymax = _ktrack->getAxis() + width/2;
|
||
|
|
||
|
for ( ; iinterval != _blockages.end() ; iinterval++ ) {
|
||
|
Box bb ( (*iinterval).getVMin(), ymin, (*iinterval).getVMax(), ymax );
|
||
|
TrackBlockage::create ( _ktrack, bb );
|
||
|
}
|
||
|
} else {
|
||
|
DbU::Unit xmin = _ktrack->getAxis() - width/2;
|
||
|
DbU::Unit xmax = _ktrack->getAxis() + width/2;
|
||
|
|
||
|
for ( ; iinterval != _blockages.end() ; iinterval++ ) {
|
||
|
Box bb ( xmin, (*iinterval).getVMin(), xmax, (*iinterval).getVMax() );
|
||
|
TrackBlockage::create ( _ktrack, bb );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BlockagesPlanes::Plane::Plane ( RoutingPlane* plane )
|
||
|
: _routingPlane(plane)
|
||
|
, _axisSpan (plane->getAxisMin(),plane->getAxisMax())
|
||
|
, _tracks ()
|
||
|
{
|
||
|
Kite::Track* ktrack = plane->getTrackByIndex(0);
|
||
|
|
||
|
for ( ; ktrack != NULL ; ktrack=ktrack->getNext() ) {
|
||
|
_tracks.push_back ( BlockagesPlanes::createTrack(ktrack) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BlockagesPlanes::Plane::~Plane ()
|
||
|
{
|
||
|
for ( size_t i=0 ; i<_tracks.size() ; i++ ) delete _tracks[i];
|
||
|
}
|
||
|
|
||
|
|
||
|
inline unsigned int BlockagesPlanes::Plane::getDirection () const { return _routingPlane->getDirection(); }
|
||
|
inline const Layer* BlockagesPlanes::Plane::getLayer () const { return _routingPlane->getLayer(); }
|
||
|
inline DbU::Unit BlockagesPlanes::Plane::getHalfWireWidth () const { return _routingPlane->getLayerGauge()->getHalfWireWidth(); }
|
||
|
inline DbU::Unit BlockagesPlanes::Plane::getPitch () const { return _routingPlane->getLayerGauge()->getPitch(); }
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::Plane::merge ( Box boundingBox )
|
||
|
{
|
||
|
ltrace(190) << "| Add on plane " << _routingPlane->getLayer() << " " << boundingBox << endl;
|
||
|
|
||
|
DbU::Unit delta = getPitch() - getHalfWireWidth() - 1;
|
||
|
|
||
|
if ( getDirection() == Constant::Horizontal ) {
|
||
|
boundingBox.inflate ( 0, delta, 0, delta );
|
||
|
|
||
|
ltrace(190) << "Track range: " << DbU::getValueString(boundingBox.getYMin())
|
||
|
<< ":" << DbU::getValueString(boundingBox.getYMax()) << endl;
|
||
|
for ( size_t i=0 ; (i<_tracks.size()) and (_tracks[i]->getAxis() < boundingBox.getYMax()) ; i++ ) {
|
||
|
if ( _tracks[i]->getAxis() < boundingBox.getYMin() ) continue;
|
||
|
|
||
|
_tracks[i]->add ( Interval(boundingBox.getXMin(),boundingBox.getXMax()) );
|
||
|
}
|
||
|
} else {
|
||
|
boundingBox.inflate ( delta, 0, delta, 0 );
|
||
|
for ( size_t i=0 ; (i<_tracks.size()) and (_tracks[i]->getAxis() < boundingBox.getXMax()) ; i++ ) {
|
||
|
if ( _tracks[i]->getAxis() < boundingBox.getXMin() ) continue;
|
||
|
|
||
|
_tracks[i]->add ( Interval(boundingBox.getYMin(),boundingBox.getYMax()) );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::Plane::dump ()
|
||
|
{
|
||
|
for ( size_t i=0 ; i<_tracks.size() ; i++ ) _tracks[i]->dump(DbU::lambda(2.0));
|
||
|
}
|
||
|
|
||
|
|
||
|
BlockagesPlanes::Track* BlockagesPlanes::createTrack ( Kite::Track* ktrack )
|
||
|
{ return new Track ( ktrack ); }
|
||
|
|
||
|
|
||
|
BlockagesPlanes::BlockagesPlanes ( KiteEngine* kite )
|
||
|
: _kite (kite)
|
||
|
, _planes ()
|
||
|
, _activePlane(NULL)
|
||
|
{
|
||
|
RoutingGauge* rg = _kite->getConfiguration()->getRoutingGauge();
|
||
|
size_t gaugeDepth = rg->getDepth ();
|
||
|
|
||
|
for ( size_t depth=0 ; depth<gaugeDepth ; depth++ ) {
|
||
|
const RegularLayer* routingLayer = dynamic_cast<const RegularLayer*>(rg->getRoutingLayer(depth));
|
||
|
if ( not routingLayer ) continue;
|
||
|
|
||
|
const BasicLayer* blockageLayer = routingLayer->getBasicLayer()->getBlockageLayer();
|
||
|
if ( not blockageLayer ) continue;
|
||
|
|
||
|
_planes.insert ( make_pair(blockageLayer,new Plane(_kite->getRoutingPlaneByIndex(depth))) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BlockagesPlanes::~BlockagesPlanes ()
|
||
|
{
|
||
|
while ( not _planes.empty() ) {
|
||
|
delete _planes.begin()->second;
|
||
|
_planes.erase ( _planes.begin() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool BlockagesPlanes::hasPlane ( const BasicLayer* basicLayer )
|
||
|
{ return (_planes.find(basicLayer) != _planes.end()); }
|
||
|
|
||
|
|
||
|
bool BlockagesPlanes::setActivePlane ( const BasicLayer* basicLayer )
|
||
|
{
|
||
|
map<const BasicLayer*,Plane*>::iterator iplane = _planes.find(basicLayer);
|
||
|
if ( iplane == _planes.end() ) return false;
|
||
|
|
||
|
_activePlane = iplane->second;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline BlockagesPlanes::Plane* BlockagesPlanes::getActivePlane () const
|
||
|
{ return _activePlane; }
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::add ( Box boundingBox )
|
||
|
{
|
||
|
if ( not _activePlane ) return;
|
||
|
_activePlane->merge ( boundingBox );
|
||
|
}
|
||
|
|
||
|
|
||
|
void BlockagesPlanes::dump ()
|
||
|
{
|
||
|
map<const BasicLayer*,Plane*>::iterator iplane = _planes.begin();
|
||
|
for ( ; iplane != _planes.end() ; iplane++ ) {
|
||
|
iplane->second->dump();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// -------------------------------------------------------------------
|
||
|
// Class : "::QueryBlockages".
|
||
|
|
||
|
|
||
|
class QueryBlockages : public Query {
|
||
|
public:
|
||
|
QueryBlockages ( KiteEngine* );
|
||
|
virtual bool hasGoCallback () const;
|
||
|
virtual void setBasicLayer ( const BasicLayer* );
|
||
|
virtual void goCallback ( Go* );
|
||
|
virtual void rubberCallback ( Rubber* );
|
||
|
virtual void extensionGoCallback ( Go* );
|
||
|
virtual void masterCellCallback ();
|
||
|
void addBlockage ( const Go* go
|
||
|
, const BasicLayer* basicLayer
|
||
|
, const Box& area
|
||
|
, const Transformation& transformation
|
||
|
);
|
||
|
virtual void doQuery ();
|
||
|
inline void dump ();
|
||
|
inline unsigned int getBlockagesCount () const;
|
||
|
private:
|
||
|
KiteEngine* _kite;
|
||
|
BlockagesPlanes _blockagesPlanes;
|
||
|
unsigned int _blockagesCount;
|
||
|
};
|
||
|
|
||
|
|
||
|
QueryBlockages::QueryBlockages ( KiteEngine* kite )
|
||
|
: Query ()
|
||
|
, _kite (kite)
|
||
|
, _blockagesPlanes(kite)
|
||
|
, _blockagesCount (0)
|
||
|
{
|
||
|
setCell ( kite->getCell() );
|
||
|
setArea ( kite->getCell()->getBoundingBox() );
|
||
|
setBasicLayer ( NULL );
|
||
|
setFilter ( Query::DoTerminalCells|Query::DoComponents );
|
||
|
}
|
||
|
|
||
|
|
||
|
inline unsigned int QueryBlockages::getBlockagesCount () const
|
||
|
{ return _blockagesCount; }
|
||
|
|
||
|
|
||
|
inline void QueryBlockages::dump ()
|
||
|
{ return _blockagesPlanes.dump(); }
|
||
|
|
||
|
|
||
|
void QueryBlockages::setBasicLayer ( const BasicLayer* basicLayer )
|
||
|
{
|
||
|
_blockagesPlanes.setActivePlane ( basicLayer );
|
||
|
Query::setBasicLayer ( basicLayer );
|
||
|
}
|
||
|
|
||
|
|
||
|
void QueryBlockages::doQuery ()
|
||
|
{
|
||
|
if ( not _blockagesPlanes.getActivePlane() ) return;
|
||
|
Query::doQuery ();
|
||
|
}
|
||
|
|
||
|
|
||
|
void QueryBlockages::masterCellCallback ()
|
||
|
{ }
|
||
|
|
||
|
|
||
|
bool QueryBlockages::hasGoCallback () const
|
||
|
{ return true; }
|
||
|
|
||
|
|
||
|
void QueryBlockages::goCallback ( Go* go )
|
||
|
{
|
||
|
addBlockage ( go, getBasicLayer(), getArea(), getTransformation() );
|
||
|
}
|
||
|
|
||
|
|
||
|
void QueryBlockages::addBlockage ( const Go* go
|
||
|
, const BasicLayer* basicLayer
|
||
|
, const Box& area
|
||
|
, const Transformation& transformation
|
||
|
)
|
||
|
{
|
||
|
const Component* component = dynamic_cast<const Component*>(go);
|
||
|
if ( component ) {
|
||
|
_blockagesCount++;
|
||
|
Box bb ( transformation.getBox(component->getBoundingBox(basicLayer)) );
|
||
|
ltrace(190) << "Blockage: " << bb << " in " << basicLayer->getName() << endl;
|
||
|
|
||
|
_blockagesPlanes.add ( bb );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void QueryBlockages::rubberCallback ( Rubber* )
|
||
|
{ }
|
||
|
|
||
|
|
||
|
void QueryBlockages::extensionGoCallback ( Go* )
|
||
|
{ }
|
||
|
|
||
|
|
||
|
} // End of anonymous namespace.
|
||
|
|
||
|
|
||
|
namespace Kite {
|
||
|
|
||
|
|
||
|
using Hurricane::DataBase;
|
||
|
using Hurricane::Technology;
|
||
|
using Hurricane::BasicLayer;
|
||
|
using Hurricane::ForEachIterator;
|
||
|
|
||
|
|
||
|
void KiteEngine::buildBlockages ()
|
||
|
{
|
||
|
cmess1 << " o Building blockages." << endl;
|
||
|
|
||
|
if ( not _obstacleNet ) {
|
||
|
_obstacleNet = getCell()->getNet("obstaclenet");
|
||
|
if ( not _obstacleNet )
|
||
|
_obstacleNet = Net::create ( getCell(), "obstaclenet" );
|
||
|
}
|
||
|
|
||
|
QueryBlockages query ( this );
|
||
|
Technology* technology = DataBase::getDB()->getTechnology();
|
||
|
|
||
|
forEach ( BasicLayer*, iLayer, technology->getBasicLayers() ) {
|
||
|
if ( iLayer->getMaterial() != BasicLayer::Material::blockage ) continue;
|
||
|
|
||
|
cmess1 << " - Blockages in " << iLayer->getName() << " ..." << endl;
|
||
|
|
||
|
query.setBasicLayer ( *iLayer );
|
||
|
query.doQuery ();
|
||
|
}
|
||
|
query.dump ();
|
||
|
cmess1 << " - " << query.getBlockagesCount() << " blockages found." << endl;
|
||
|
|
||
|
Session::revalidate ();
|
||
|
}
|
||
|
|
||
|
|
||
|
} // End of Kite namespace.
|