One Layer, one Cell extraction implementation in Tramontana.
* New: Tramontana::Equipotential, implemented. * Change: Tramontana::Tile, add UnionFind capabilities and Equipotential attribute. * New: Tramontana::SweepLine, build upon Hurricane::IntervalTree, can now perform a "one layer only" extraction (checked with "metal1").
This commit is contained in:
parent
5879a5b581
commit
8f387620cb
|
@ -9,14 +9,20 @@
|
|||
${Boost_INCLUDE_DIRS}
|
||||
${Python_INCLUDE_DIRS}
|
||||
)
|
||||
set( includes tramontana/TramontanaEngine.h
|
||||
set( includes tramontana/Tile.h
|
||||
tramontana/SweepLine.h
|
||||
tramontana/Equipotential.h
|
||||
tramontana/TramontanaEngine.h
|
||||
tramontana/GraphicTramontanaEngine.h
|
||||
)
|
||||
set( pyIncludes tramontana/PyTramontanaEngine.h
|
||||
tramontana/PyGraphicTramontanaEngine.h
|
||||
)
|
||||
set( mocIncludes tramontana/GraphicTramontanaEngine.h )
|
||||
set( cpps TramontanaEngine.cpp
|
||||
set( cpps Tile.cpp
|
||||
SweepLine.cpp
|
||||
Equipotential.cpp
|
||||
TramontanaEngine.cpp
|
||||
GraphicTramontanaEngine.cpp
|
||||
)
|
||||
set( pyCpps PyTramontana.cpp
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./Equipotential.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include "hurricane/utilities/Path.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/UpdateSession.h"
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/Timer.h"
|
||||
#include "hurricane/Layer.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Pad.h"
|
||||
#include "hurricane/Plug.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Instance.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
#include "tramontana/Equipotential.h"
|
||||
#include "tramontana/TramontanaEngine.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::dec;
|
||||
using std::setw;
|
||||
using std::setfill;
|
||||
using std::left;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using std::ostringstream;
|
||||
using std::setprecision;
|
||||
using std::vector;
|
||||
using std::make_pair;
|
||||
using Hurricane::dbo_ptr;
|
||||
using Hurricane::UpdateSession;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::Entity;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Instance;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::Equipotential".
|
||||
|
||||
|
||||
Equipotential::Equipotential ( Cell* owner )
|
||||
: _owner (owner)
|
||||
, _boundingBox()
|
||||
, _components ()
|
||||
, _childs ()
|
||||
{ }
|
||||
|
||||
|
||||
void Equipotential::_postCreate ()
|
||||
{
|
||||
Super::_postCreate();
|
||||
TramontanaEngine* tramontana = TramontanaEngine::get( _owner );
|
||||
tramontana->add( this );
|
||||
}
|
||||
|
||||
|
||||
Equipotential* Equipotential::create ( Cell* owner )
|
||||
{
|
||||
Equipotential* equi = new Equipotential ( owner );
|
||||
equi->_postCreate();
|
||||
return equi;
|
||||
}
|
||||
|
||||
|
||||
void Equipotential::_preDestroy ()
|
||||
{
|
||||
Super::_preDestroy();
|
||||
}
|
||||
|
||||
|
||||
Equipotential::~Equipotential ()
|
||||
{ }
|
||||
|
||||
|
||||
Cell* Equipotential::getCell () const
|
||||
{ return _owner; }
|
||||
|
||||
|
||||
Box Equipotential::getBoundingBox () const
|
||||
{ return _boundingBox; }
|
||||
|
||||
|
||||
void Equipotential::add ( Component* component )
|
||||
{
|
||||
_components.insert( component );
|
||||
}
|
||||
|
||||
|
||||
void Equipotential::add ( Occurrence child )
|
||||
{
|
||||
if (child.getPath().isEmpty())
|
||||
add( dynamic_cast<Component*>( child.getEntity() ));
|
||||
else
|
||||
_childs.push_back( child );
|
||||
}
|
||||
|
||||
|
||||
void Equipotential::merge ( Equipotential* other )
|
||||
{
|
||||
if (this == other) {
|
||||
cerr << Warning( "Equipotential::merge(): Attempt to merge itself (ignored).\n"
|
||||
" (on: %s)"
|
||||
, getString(this).c_str()
|
||||
) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for ( Component* component : other->getComponents() ) {
|
||||
add( component );
|
||||
}
|
||||
for ( Occurrence child : other->getChilds() ) {
|
||||
add( child );
|
||||
}
|
||||
other->clear();
|
||||
}
|
||||
|
||||
|
||||
void Equipotential::clear ()
|
||||
{
|
||||
_components.clear();
|
||||
_childs .clear();
|
||||
}
|
||||
|
||||
|
||||
string Equipotential::_getTypeName () const
|
||||
{ return "Tramontana::Equipotential"; }
|
||||
|
||||
|
||||
string Equipotential::_getString () const
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<Equipotential id:" << getId() << " " << _owner->getName() << ">";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
Record* Equipotential::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
if (record) {
|
||||
record->add( getSlot( "_owner" , &_owner ) );
|
||||
record->add( getSlot( "_boundingBox", &_boundingBox ) );
|
||||
record->add( getSlot( "_components" , &_components ) );
|
||||
record->add( getSlot( "_childs" , &_childs ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
|
@ -140,6 +140,24 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyTramontanaEngine_extract ( PyTramontanaEngine* self )
|
||||
{
|
||||
cdebug_log(40,0) << "PyTramontanaEngine_extract()" << endl;
|
||||
HTRY
|
||||
METHOD_HEAD("TramontanaEngine.extract()")
|
||||
if (tramontana->getViewer()) {
|
||||
if (ExceptionWidget::catchAllWrapper( std::bind(&TramontanaEngine::extract,tramontana) )) {
|
||||
PyErr_SetString( HurricaneError, "TramontanaEngine::extract() has thrown an exception (C++)." );
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
tramontana->extract();
|
||||
}
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// Standart Accessors (Attributes).
|
||||
|
||||
// Standart Destroy (Attribute).
|
||||
|
@ -151,8 +169,12 @@ extern "C" {
|
|||
, "Returns the Tramontana engine attached to the Cell, None if there isnt't." }
|
||||
, { "create" , (PyCFunction)PyTramontanaEngine_create , METH_VARARGS|METH_STATIC
|
||||
, "Create a Tramontana engine on this cell." }
|
||||
, { "destroy" , (PyCFunction)PyTramontanaEngine_destroy , METH_NOARGS
|
||||
, "Destroy a Tramontana engine." }
|
||||
, { "setViewer" , (PyCFunction)PyTramontanaEngine_setViewer , METH_VARARGS
|
||||
, "Associate a Viewer to this TramontanaEngine." }
|
||||
, { "extract" , (PyCFunction)PyTramontanaEngine_extract , METH_NOARGS
|
||||
, "Perform the layout extraction." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./SweepLine.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include "hurricane/utilities/Path.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/UpdateSession.h"
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/Timer.h"
|
||||
#include "hurricane/DataBase.h"
|
||||
#include "hurricane/Technology.h"
|
||||
#include "hurricane/Layer.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Pad.h"
|
||||
#include "hurricane/Plug.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Instance.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
#include "tramontana/SweepLine.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::dec;
|
||||
using std::setw;
|
||||
using std::setfill;
|
||||
using std::left;
|
||||
using std::right;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using std::ostringstream;
|
||||
using std::setprecision;
|
||||
using std::vector;
|
||||
using std::make_pair;
|
||||
using Hurricane::dbo_ptr;
|
||||
using Hurricane::UpdateSession;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::Interval;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::DataBase;
|
||||
using Hurricane::Technology;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::Entity;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Instance;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::SweepLine".
|
||||
|
||||
|
||||
SweepLine::SweepLine ( TramontanaEngine* tramontana )
|
||||
: _tramontana (tramontana)
|
||||
, _tiles ()
|
||||
, _intervalTree()
|
||||
{ }
|
||||
|
||||
|
||||
SweepLine::~SweepLine ()
|
||||
{ }
|
||||
|
||||
|
||||
void SweepLine::run ()
|
||||
{
|
||||
BasicLayer* layer = DataBase::getDB()->getTechnology()->getBasicLayer( "metal1" );
|
||||
loadTiles( layer );
|
||||
for ( Element& element : _tiles ) {
|
||||
Tile* tile = element.getTile();
|
||||
TileIntv tileIntv ( tile, tile->getYMin(), tile->getYMax() );
|
||||
cerr << right << setw(10) << DbU::getValueString(element.getX()) << " > " << tile << endl;
|
||||
if (element.isLeftEdge()) {
|
||||
for ( const TileIntv& overlap : _intervalTree.getOverlaps(
|
||||
Interval(tile->getYMin(), tile->getYMax() ))) {
|
||||
cerr << " | intersect " << overlap.getData() << endl;
|
||||
tile->merge( overlap.getData() );
|
||||
}
|
||||
_intervalTree.insert( tileIntv );
|
||||
} else {
|
||||
_intervalTree.remove( tileIntv );
|
||||
}
|
||||
}
|
||||
mergeEquipotentials();
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::loadTiles ( const BasicLayer* layer )
|
||||
{
|
||||
cerr << "SweepLine::run()" << endl;
|
||||
for ( Occurrence occurrence : getCell()->getOccurrencesUnder( getCell()->getBoundingBox() ) ) {
|
||||
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||
if (not component) continue;
|
||||
if (not component->getLayer()->contains(layer)) continue;
|
||||
Tile* tile = Tile::create( occurrence, layer );
|
||||
_tiles.push_back( Element( tile, Tile::LeftEdge ) );
|
||||
_tiles.push_back( Element( tile, Tile::RightEdge ) );
|
||||
}
|
||||
sort( _tiles.begin(), _tiles.end() );
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::mergeEquipotentials ()
|
||||
{
|
||||
Tile::timeTick();
|
||||
for ( Tile* tile : Tile::getAllTiles() ) {
|
||||
tile->getRoot( Tile::MergeEqui );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string SweepLine::_getTypeName () const
|
||||
{ return "Tramontana::SweepLine"; }
|
||||
|
||||
|
||||
string SweepLine::_getString () const
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<SweepLine \"" << _tramontana->getCell()->getName() << "\">";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
Record* SweepLine::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
if (record) {
|
||||
record->add( getSlot( "_tramontana" , &_tramontana ) );
|
||||
record->add( getSlot( "_tiles" , &_tiles ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
|
@ -0,0 +1,239 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./Tile.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
#include "hurricane/utilities/Path.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/UpdateSession.h"
|
||||
#include "hurricane/Bug.h"
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/Timer.h"
|
||||
#include "hurricane/Layer.h"
|
||||
#include "hurricane/Net.h"
|
||||
#include "hurricane/Pad.h"
|
||||
#include "hurricane/Plug.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "hurricane/Instance.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/Horizontal.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
#include "tramontana/Tile.h"
|
||||
#include "tramontana/Equipotential.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::dec;
|
||||
using std::setw;
|
||||
using std::setfill;
|
||||
using std::left;
|
||||
using std::string;
|
||||
using std::ostream;
|
||||
using std::ofstream;
|
||||
using std::ostringstream;
|
||||
using std::setprecision;
|
||||
using std::vector;
|
||||
using std::make_pair;
|
||||
using Hurricane::dbo_ptr;
|
||||
using Hurricane::UpdateSession;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::tab;
|
||||
using Hurricane::Bug;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::Entity;
|
||||
using Hurricane::Horizontal;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Instance;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::Tile".
|
||||
|
||||
|
||||
uint32_t Tile::_time = 0;
|
||||
vector<Tile*> Tile::_allocateds;
|
||||
|
||||
|
||||
Tile::Tile ( Occurrence occurrence, const BasicLayer* layer, const Box& boundingBox )
|
||||
: _occurrence (occurrence)
|
||||
, _layer (layer)
|
||||
, _boundingBox (boundingBox)
|
||||
, _equipotential(nullptr)
|
||||
, _flags (0)
|
||||
, _parent (nullptr)
|
||||
, _rank (0)
|
||||
, _timeStamp (0)
|
||||
{
|
||||
_allocateds.push_back( this );
|
||||
}
|
||||
|
||||
|
||||
Tile* Tile::create ( Occurrence occurrence, const BasicLayer* layer )
|
||||
{
|
||||
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||
if (not component) {
|
||||
cerr << Error( "Tile::create(): Must be build over an occurrence of *Component*.\n"
|
||||
" (%s)"
|
||||
, getString(occurrence).c_str()
|
||||
) << endl;
|
||||
return nullptr;
|
||||
}
|
||||
if (not component->getLayer()->contains(layer)) {
|
||||
cerr << Error( "Tile::create(): Component layer does not contains \"%s\".\n"
|
||||
" (%s)"
|
||||
, getString(layer->getName()).c_str()
|
||||
, getString(occurrence).c_str()
|
||||
) << endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Box bb = component->getBoundingBox( layer );
|
||||
occurrence.getPath().getTransformation().applyOn( bb );
|
||||
Tile* tile = new Tile ( occurrence, layer, bb );
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
|
||||
void Tile::destroy ()
|
||||
{
|
||||
cdebug_log(160,1) << "Tile::destroy() " << this << endl;
|
||||
cdebug_tabw(160,-1);
|
||||
}
|
||||
|
||||
|
||||
Tile::~Tile ()
|
||||
{ }
|
||||
|
||||
|
||||
Tile* Tile::getRoot ( uint32_t flags )
|
||||
{
|
||||
if (not getParent() and (not (flags & MergeEqui))) return this;
|
||||
|
||||
Tile* root = this;
|
||||
while ( root->getParent() ) {
|
||||
if (flags & MergeEqui) {
|
||||
if (not root->getParent()->getEquipotential() and root->getEquipotential())
|
||||
root->getParent()->setEquipotential( root->getEquipotential() );
|
||||
}
|
||||
root = root->getParent();
|
||||
}
|
||||
|
||||
if (flags & Compress) {
|
||||
Tile* current = this;
|
||||
while ( current != root ) {
|
||||
Tile* curParent = current->getParent();
|
||||
current->setParent( root );
|
||||
current = curParent;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & MergeEqui) {
|
||||
Equipotential* rootEqui = root->getEquipotential();
|
||||
if (not rootEqui)
|
||||
rootEqui = root->newEquipotential();
|
||||
|
||||
Tile* current = this;
|
||||
while ( current ) {
|
||||
if (current->isUpToDate()) break;
|
||||
if (current->getEquipotential()) {
|
||||
if (current->getEquipotential() != rootEqui)
|
||||
rootEqui->merge( current->getEquipotential() );
|
||||
} else {
|
||||
rootEqui->add( current->getOccurrence() );
|
||||
}
|
||||
current->syncTime();
|
||||
current = current->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
Tile* Tile::merge ( Tile* other )
|
||||
{
|
||||
Tile* root1 = getRoot();
|
||||
Tile* root2 = other->getRoot();
|
||||
if (root1 and (root1 == root2)) return root1;
|
||||
|
||||
if (root1->getRank() < root2->getRank())
|
||||
std::swap( root1, root2 );
|
||||
if (root1->getRank() == root2->getRank())
|
||||
root1->incRank();
|
||||
root2->setParent( root1 );
|
||||
// Fuse root2 into root1 here!
|
||||
|
||||
return root1;
|
||||
}
|
||||
|
||||
|
||||
Equipotential* Tile::newEquipotential ()
|
||||
{
|
||||
if (_equipotential) {
|
||||
cerr << Error( "Tile::newEquipotential(): Equipotential already created (ignoring).\n"
|
||||
" (on: %s)"
|
||||
, getString(this).c_str()
|
||||
) << endl;
|
||||
return _equipotential;
|
||||
}
|
||||
|
||||
_equipotential = Equipotential::create( _occurrence.getOwnerCell() );
|
||||
_equipotential->add( _occurrence );
|
||||
return _equipotential;
|
||||
}
|
||||
|
||||
|
||||
string Tile::_getTypeName () const
|
||||
{ return "Tramontana::Tile"; }
|
||||
|
||||
|
||||
string Tile::_getString () const
|
||||
{
|
||||
ostringstream os;
|
||||
os << "<Tile " << _boundingBox << " " << _layer->getName() << " " << _occurrence << ">";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
Record* Tile::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
if (record) {
|
||||
record->add( getSlot( "_occurrence" , &_occurrence ) );
|
||||
record->add( getSlot( "_layer" , _layer ) );
|
||||
record->add( getSlot( "_boundingBox", &_boundingBox ) );
|
||||
record->add( getSlot( "_flags" , &_flags ) );
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
|
@ -41,6 +41,7 @@
|
|||
#include "crlcore/Measures.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
#include "crlcore/AllianceFramework.h"
|
||||
#include "tramontana/SweepLine.h"
|
||||
#include "tramontana/TramontanaEngine.h"
|
||||
|
||||
|
||||
|
@ -100,8 +101,9 @@ namespace Tramontana {
|
|||
|
||||
|
||||
TramontanaEngine::TramontanaEngine ( Cell* cell )
|
||||
: Super (cell)
|
||||
, _viewer (NULL)
|
||||
: Super (cell)
|
||||
, _viewer (NULL)
|
||||
, _equipotentials()
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -144,9 +146,29 @@ namespace Tramontana {
|
|||
void TramontanaEngine::extract ()
|
||||
{
|
||||
cerr << "TramontanaEngine::extract() called on " << getCell() << endl;
|
||||
SweepLine sweepLine ( this );
|
||||
sweepLine.run();
|
||||
showEquipotentials();
|
||||
}
|
||||
|
||||
|
||||
void TramontanaEngine::showEquipotentials () const
|
||||
{
|
||||
cerr << "Equipotentials:" << endl;
|
||||
for ( Equipotential* equi : _equipotentials ) {
|
||||
cerr << equi << endl;
|
||||
for ( Component* component : equi->getComponents() ) {
|
||||
cerr << "| " << component << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TramontanaEngine::add ( Equipotential* equi )
|
||||
{
|
||||
_equipotentials.insert( equi );
|
||||
}
|
||||
|
||||
|
||||
string TramontanaEngine::_getTypeName () const
|
||||
{ return "Tramontana::TramontanaEngine"; }
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/Equipotential.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "hurricane/Component.h"
|
||||
#include "hurricane/Occurrence.h"
|
||||
namespace Hurricane {
|
||||
class Net;
|
||||
}
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Record;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::DBo;
|
||||
using Hurricane::Entity;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::BasicLayer;
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Component;
|
||||
using Hurricane::Occurrence;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::Equipotential".
|
||||
|
||||
class Equipotential : public Entity {
|
||||
public:
|
||||
typedef Entity Super;
|
||||
typedef std::set<Component*,DBo::CompareById> ComponentSet;
|
||||
public:
|
||||
static Equipotential* create ( Cell* );
|
||||
inline bool isEmpty () const;
|
||||
virtual Cell* getCell () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
inline bool hasComponent ( Component* ) const;
|
||||
void add ( Component* );
|
||||
void add ( Occurrence );
|
||||
void merge ( Equipotential* );
|
||||
void clear ();
|
||||
inline const ComponentSet& getComponents () const;
|
||||
inline const std::vector<Occurrence>& getChilds () const;
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
std::string _getTypeName () const;
|
||||
protected:
|
||||
virtual void _postCreate ();
|
||||
virtual void _preDestroy ();
|
||||
private:
|
||||
Equipotential ( Cell* );
|
||||
~Equipotential ();
|
||||
private:
|
||||
Equipotential ( const Equipotential& ) = delete;
|
||||
Equipotential& operator= ( const Equipotential& ) = delete;
|
||||
private:
|
||||
Cell* _owner;
|
||||
Box _boundingBox;
|
||||
ComponentSet _components;
|
||||
std::vector<Occurrence> _childs;
|
||||
};
|
||||
|
||||
|
||||
|
||||
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
|
||||
inline const Equipotential::ComponentSet& Equipotential::getComponents () const { return _components; }
|
||||
inline const std::vector<Occurrence>& Equipotential::getChilds () const { return _childs; }
|
||||
|
||||
inline bool Equipotential::hasComponent ( Component* component ) const
|
||||
{ return _components.find( component ) != _components.end(); }
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Tramontana::Equipotential);
|
|
@ -0,0 +1,100 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/SweepLine.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "hurricane/BasicLayer.h"
|
||||
namespace Hurricane {
|
||||
class Net;
|
||||
}
|
||||
#include "tramontana/Tile.h"
|
||||
#include "tramontana/TramontanaEngine.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Record;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Cell;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::SweepLine".
|
||||
|
||||
class SweepLine {
|
||||
private:
|
||||
class Element {
|
||||
public:
|
||||
inline Element ( Tile*, uint32_t flags );
|
||||
inline bool operator< ( const Element& ) const;
|
||||
inline bool isLeftEdge () const;
|
||||
inline Tile* getTile () const;
|
||||
inline DbU::Unit getX () const;
|
||||
inline DbU::Unit getY () const;
|
||||
inline DbU::Unit getId () const;
|
||||
private:
|
||||
Tile* _tile;
|
||||
uint32_t _flags;
|
||||
};
|
||||
public:
|
||||
SweepLine ( TramontanaEngine* );
|
||||
~SweepLine ();
|
||||
inline Cell* getCell ();
|
||||
void run ();
|
||||
void loadTiles ( const BasicLayer* );
|
||||
void mergeEquipotentials ();
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
std::string _getTypeName () const;
|
||||
private:
|
||||
SweepLine ( const SweepLine& ) = delete;
|
||||
SweepLine& operator= ( const SweepLine& ) = delete;
|
||||
private:
|
||||
TramontanaEngine* _tramontana;
|
||||
std::vector<Element> _tiles;
|
||||
TileIntvTree _intervalTree;
|
||||
};
|
||||
|
||||
|
||||
// SweepLine::Element.
|
||||
inline SweepLine::Element::Element ( Tile* tile, uint32_t flags ) : _tile(tile), _flags(flags) { }
|
||||
inline bool SweepLine::Element::isLeftEdge () const { return _flags & Tile::LeftEdge; }
|
||||
inline Tile* SweepLine::Element::getTile () const { return _tile; }
|
||||
inline DbU::Unit SweepLine::Element::getX () const { return isLeftEdge() ? _tile->getLeftEdge() : _tile->getRightEdge(); }
|
||||
inline DbU::Unit SweepLine::Element::getY () const { return _tile->getBoundingBox().getYMin(); }
|
||||
inline DbU::Unit SweepLine::Element::getId () const { return _tile->getId(); }
|
||||
|
||||
inline bool SweepLine::Element::operator< ( const Element& rhs ) const
|
||||
{
|
||||
if (getX() != rhs.getX()) return (getX() < rhs.getX());
|
||||
if (getY() != rhs.getY()) return (getY() < rhs.getY());
|
||||
return getId() < rhs.getId();
|
||||
}
|
||||
|
||||
|
||||
// SweepLine.
|
||||
inline Cell* SweepLine::getCell () { return _tramontana->getCell(); }
|
||||
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Tramontana::SweepLine);
|
|
@ -0,0 +1,142 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | T r a m o n t a n a - Extractor & LVX |
|
||||
// | |
|
||||
// | Algorithm : Christian MASSON |
|
||||
// | First impl. : Yifei WU |
|
||||
// | Second impl. : Jean-Paul CHAPUT |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./tramontana/Tile.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "hurricane/Box.h"
|
||||
#include "hurricane/BasicLayer.h"
|
||||
#include "hurricane/Component.h"
|
||||
#include "hurricane/Occurrence.h"
|
||||
#include "hurricane/IntervalTree.h"
|
||||
namespace Hurricane {
|
||||
class Net;
|
||||
}
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
||||
using Hurricane::Record;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Layer;
|
||||
using Hurricane::BasicLayer;
|
||||
using Hurricane::Net;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Component;
|
||||
using Hurricane::Occurrence;
|
||||
using Hurricane::RbTree;
|
||||
using Hurricane::IntervalData;
|
||||
using Hurricane::IntervalTree;
|
||||
class Equipotential;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::Tile".
|
||||
|
||||
class Tile {
|
||||
public:
|
||||
static const uint32_t NoFlags = 0;
|
||||
static const uint32_t LeftEdge = (1<<0);
|
||||
static const uint32_t RightEdge = (1<<1);
|
||||
static const uint32_t Compress = (1<<2);
|
||||
static const uint32_t MergeEqui = (1<<3);
|
||||
public:
|
||||
static inline const std::vector<Tile*> getAllTiles ();
|
||||
static inline void timeTick ();
|
||||
static Tile* create ( Occurrence, const BasicLayer* );
|
||||
void destroy ();
|
||||
inline bool isUpToDate () const;
|
||||
inline unsigned int getId () const;
|
||||
inline uint32_t getRank () const;
|
||||
inline Tile* getParent () const;
|
||||
Tile* getRoot ( uint32_t flags=Compress );
|
||||
inline Component* getComponent () const;
|
||||
inline Occurrence getOccurrence () const;
|
||||
inline const BasicLayer* getLayer () const;
|
||||
inline const Box& getBoundingBox () const;
|
||||
inline Equipotential* getEquipotential () const;
|
||||
inline DbU::Unit getLeftEdge () const;
|
||||
inline DbU::Unit getRightEdge () const;
|
||||
inline DbU::Unit getYMin () const;
|
||||
inline DbU::Unit getYMax () const;
|
||||
inline uint32_t getFlags () const;
|
||||
inline void incRank ();
|
||||
inline void syncTime ();
|
||||
inline void setParent ( Tile* );
|
||||
Tile* merge ( Tile* );
|
||||
inline void setEquipotential ( Equipotential* );
|
||||
Equipotential* newEquipotential ();
|
||||
Record* _getRecord () const;
|
||||
std::string _getString () const;
|
||||
std::string _getTypeName () const;
|
||||
private:
|
||||
Tile ( Occurrence, const BasicLayer*, const Box& );
|
||||
~Tile ();
|
||||
private:
|
||||
Tile ( const Tile& ) = delete;
|
||||
Tile& operator= ( const Tile& ) = delete;
|
||||
private:
|
||||
static uint32_t _time;
|
||||
static std::vector<Tile*> _allocateds;
|
||||
Occurrence _occurrence;
|
||||
const BasicLayer* _layer;
|
||||
Box _boundingBox;
|
||||
Equipotential* _equipotential;
|
||||
uint32_t _flags;
|
||||
Tile* _parent;
|
||||
uint32_t _rank;
|
||||
uint32_t _timeStamp;
|
||||
};
|
||||
|
||||
inline const std::vector<Tile*> Tile::getAllTiles () { return _allocateds; }
|
||||
inline void Tile::timeTick () { _time++; }
|
||||
inline bool Tile::isUpToDate () const { return _timeStamp >= _time; }
|
||||
inline unsigned int Tile::getId () const { return getComponent()->getId(); }
|
||||
inline Component* Tile::getComponent () const { return dynamic_cast<Component*>( _occurrence.getEntity() ); }
|
||||
inline Occurrence Tile::getOccurrence () const { return _occurrence; }
|
||||
inline const BasicLayer* Tile::getLayer () const { return _layer; }
|
||||
inline const Box& Tile::getBoundingBox () const { return _boundingBox; }
|
||||
inline Equipotential* Tile::getEquipotential () const { return _equipotential; }
|
||||
inline DbU::Unit Tile::getLeftEdge () const { return _boundingBox.getXMin(); }
|
||||
inline DbU::Unit Tile::getRightEdge () const { return _boundingBox.getXMax(); }
|
||||
inline DbU::Unit Tile::getYMin () const { return _boundingBox.getYMin(); }
|
||||
inline DbU::Unit Tile::getYMax () const { return _boundingBox.getYMax(); }
|
||||
inline uint32_t Tile::getFlags () const { return _flags; }
|
||||
inline uint32_t Tile::getRank () const { return _rank; }
|
||||
inline Tile* Tile::getParent () const { return _parent; }
|
||||
inline void Tile::incRank () { _rank++; }
|
||||
inline void Tile::syncTime () { _timeStamp=_time; }
|
||||
inline void Tile::setParent ( Tile* parent ) { _parent=parent; }
|
||||
inline void Tile::setEquipotential ( Equipotential* equi ) { _equipotential=equi; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Tramontana::TileIntvTree".
|
||||
|
||||
|
||||
typedef IntervalData<Tile*> TileIntv;
|
||||
typedef IntervalTree<Tile*> TileIntvTree;
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Tramontana::Tile);
|
||||
INSPECTOR_PR_SUPPORT(Tramontana::TileIntv);
|
||||
INSPECTOR_PR_SUPPORT(Tramontana::TileIntvTree);
|
|
@ -27,6 +27,7 @@ namespace Hurricane {
|
|||
class CellViewer;
|
||||
}
|
||||
#include "crlcore/ToolEngine.h"
|
||||
#include "tramontana/Equipotential.h"
|
||||
|
||||
|
||||
namespace Tramontana {
|
||||
|
@ -53,15 +54,19 @@ namespace Tramontana {
|
|||
public:
|
||||
const Name& getName () const;
|
||||
inline void setViewer ( CellViewer* );
|
||||
inline CellViewer* getViewer ();
|
||||
void extract ();
|
||||
void showEquipotentials () const;
|
||||
void add ( Equipotential* );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual std::string _getString () const;
|
||||
virtual std::string _getTypeName () const;
|
||||
private:
|
||||
// Attributes.
|
||||
static Name _toolName;
|
||||
protected:
|
||||
private:
|
||||
CellViewer* _viewer;
|
||||
std::set<Equipotential*,DBo::CompareById> _equipotentials;
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
TramontanaEngine ( Cell* );
|
||||
|
@ -74,7 +79,8 @@ namespace Tramontana {
|
|||
};
|
||||
|
||||
|
||||
inline void TramontanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
|
||||
inline void TramontanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
|
||||
inline CellViewer* TramontanaEngine::getViewer () { return _viewer; }
|
||||
|
||||
|
||||
} // Tramontana namespace.
|
||||
|
|
Loading…
Reference in New Issue