diff --git a/hurricane/src/hurricane/Rectilinear.cpp b/hurricane/src/hurricane/Rectilinear.cpp index 42bc911b..825d776a 100644 --- a/hurricane/src/hurricane/Rectilinear.cpp +++ b/hurricane/src/hurricane/Rectilinear.cpp @@ -182,7 +182,7 @@ namespace { void SweepLine::loadVEdges () { const vector& points = _rectilinear->getPoints(); - for ( size_t i=0 ; i 1000) - throw Error( "Rectilinear::create(): Rectlinear polygons must not exceed 1000 vertexes." ); + throw Error( "Rectilinear::create(): Rectilinear polygons must not exceed 1000 vertexes." ); + + if (points[0] != points[points.size()-1]) + throw Error( "Rectilinear::create(): First and last point must be the same.\n" + "0:%s %d:%s" + , getString(points[0]).c_str() + , points.size()-1 + , getString(points[points.size()-1]).c_str() + ); bool isRect = true; DbU::Unit oneGrid = DbU::fromGrid( 1.0 ); diff --git a/tramontana/src/QueryTiles.cpp b/tramontana/src/QueryTiles.cpp index eb3f4833..0a72edfe 100644 --- a/tramontana/src/QueryTiles.cpp +++ b/tramontana/src/QueryTiles.cpp @@ -72,18 +72,32 @@ namespace Tramontana { void QueryTiles::goCallback ( Go* go ) { - vector tiles; + Tile* rootTile = nullptr; Component* component = dynamic_cast( go ); if (not component) return; if (isProcessed(component)) return; Occurrence occurrence = Occurrence( go, getPath() ); for ( const BasicLayer* layer : _sweepLine->getExtracteds() ) { if (not component->getLayer()->getMask().intersect(layer->getMask())) continue; - tiles.push_back( Tile::create( occurrence, layer )); - _sweepLine->add( tiles.back() ); - if (tiles.size() > 1) - tiles.back()->setParent( tiles[0] ); + Tile* tile = Tile::create( occurrence + , layer + , rootTile + , _sweepLine ); + if (not rootTile) rootTile = tile; } + + BasicLayer* cutLayer = component->getLayer()->getBasicLayers().getFirst(); + if (cutLayer->getMaterial() == BasicLayer::Material::cut) { + const SweepLine::LayerSet& connexSet = _sweepLine->getCutConnexLayers( cutLayer ); + for ( const BasicLayer* connexLayer : connexSet ) { + Tile::create( occurrence + , connexLayer + , rootTile + , _sweepLine + , Tile::ForceLayer ); + } + } + _goMatchCount++; } diff --git a/tramontana/src/SweepLine.cpp b/tramontana/src/SweepLine.cpp index 5850683f..5a6f51f3 100644 --- a/tramontana/src/SweepLine.cpp +++ b/tramontana/src/SweepLine.cpp @@ -28,6 +28,7 @@ #include "hurricane/DataBase.h" #include "hurricane/Technology.h" #include "hurricane/Layer.h" +#include "hurricane/ViaLayer.h" #include "hurricane/Net.h" #include "hurricane/Pad.h" #include "hurricane/Plug.h" @@ -71,6 +72,7 @@ namespace Tramontana { using Hurricane::DataBase; using Hurricane::Technology; using Hurricane::Layer; + using Hurricane::ViaLayer; using Hurricane::Entity; using Hurricane::Horizontal; using Hurricane::Vertical; @@ -84,18 +86,24 @@ namespace Tramontana { SweepLine::SweepLine ( TramontanaEngine* tramontana ) - : _tramontana (tramontana) - , _extracteds () - , _tiles () - , _intervalTrees() + : _tramontana (tramontana) + , _extracteds () + , _extractedsMask() + , _connexityMap () + , _tiles () + , _intervalTrees () { for ( const BasicLayer* bl : DataBase::getDB()->getTechnology()->getBasicLayers() ) { // HARDCODED. Should read the gauge. if (getString(bl->getName()).substr(0,6) == "gmetal") continue; if ( (bl->getMaterial() == BasicLayer::Material::metal) - or (bl->getMaterial() == BasicLayer::Material::poly)) + or (bl->getMaterial() == BasicLayer::Material::poly) + or (bl->getMaterial() == BasicLayer::Material::cut)) { _extracteds.push_back( bl ); + _extractedsMask |= bl->getMask(); + } } + _buildCutConnexMap(); // _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal5" )); // _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal4" )); @@ -110,16 +118,66 @@ namespace Tramontana { { } + void SweepLine::_buildCutConnexMap () + { + for ( const ViaLayer* viaLayer : DataBase::getDB()->getTechnology()->getViaLayers() ) { + const BasicLayer* cutLayer = nullptr; + for ( const BasicLayer* layer : viaLayer->getBasicLayers() ) { + if (layer->getMaterial() == BasicLayer::Material::cut) { + cutLayer = layer; + break; + } + } + if (not cutLayer) { + cerr << Error( "SweepLine::_buildConnexityMap(): ViaLayer \"%s\" does not contains any *cut* (ignored)." + , getString(viaLayer->getName()).c_str() + ) << endl; + continue; + } + auto iCutMap = _connexityMap.find( cutLayer ); + if (iCutMap == _connexityMap.end()) { + _connexityMap.insert( make_pair( cutLayer, LayerSet() )); + iCutMap = _connexityMap.find( cutLayer ); + } + for ( const BasicLayer* layer : viaLayer->getBasicLayers() ) { + if ( (layer->getMaterial() != BasicLayer::Material::cut) + and (_extractedsMask.intersect(layer->getMask())) ) { + iCutMap->second.insert( layer ); + } + } + } + // for ( auto item : _connexityMap ) { + // cerr << "BasicLayers connex to cut: " << item.first << endl; + // for ( const BasicLayer* bl : item.second ) { + // cerr << "| " << bl << endl; + // } + // } + } + + + const SweepLine::LayerSet& SweepLine::getCutConnexLayers ( const BasicLayer* cutLayer ) const + { + static LayerSet emptySet; + auto iCutMap = _connexityMap.find( cutLayer ); + if (iCutMap == _connexityMap.end()) + return emptySet; + return iCutMap->second; + } + + void SweepLine::run () { //DebugSession::open( 160, 169 ); cdebug_log(160,1) << "SweepLine::run()" << endl; loadTiles(); //bool debugOn = false; - bool written = false; + //bool written = false; for ( Element& element : _tiles ) { Tile* tile = element.getTile(); TileIntv tileIntv ( tile, tile->getYMin(), tile->getYMax() ); + // if (tile->getOccurrence().getEntity()->getId() == 3348) { + // DebugSession::open( 160, 169 ); + // } // if (getString(tile->getNet()->getName()) == "a(13)") { // cerr << tile << endl; // } @@ -143,9 +201,8 @@ namespace Tramontana { continue; } if (element.isLeftEdge()) { - // if (tile->getId() == 46055) { - // DebugSession::open( 0, 169 ); - // if (not written) intvTree->second.write( "tree-before.gv" ); + // if (tile->getOccurrence().getEntity()->getId() == 3348) { + // //if (not written) intvTree->second.write( "tree-before.gv" ); // cdebug_log(160,0) << " Interval tree *before* insertion." << endl; // for ( auto elt : intvTree->second.getElements() ) { // cdebug_log(160,0) << " | in tree:" << elt << endl; @@ -167,11 +224,10 @@ namespace Tramontana { // cerr << " | insert " << tile << endl; // } intvTree->second.insert( tileIntv ); - // if (tile->getId() == 46055) { - // if (not written) intvTree->second.write( "tree-after.gv" ); - // written = true; - // DebugSession::close(); - // } + if (tile->getOccurrence().getEntity()->getId() == 3348) { + //if (not written) intvTree->second.write( "tree-after.gv" ); + //written = true; + } } else { // if (tile->getId() == 289) { // DebugSession::open( 0, 169 ); @@ -218,7 +274,10 @@ namespace Tramontana { // } } //intvTree->second.checkVMax(); - cdebug_tabw(160,-1); + // cdebug_tabw(160,-1); + // if (tile->getOccurrence().getEntity()->getId() == 3348) { + // DebugSession::close(); + // } } //if (debugOn) DebugSession::close(); cdebug_tabw(160,-1); diff --git a/tramontana/src/Tile.cpp b/tramontana/src/Tile.cpp index 648e882b..45e0d5a2 100644 --- a/tramontana/src/Tile.cpp +++ b/tramontana/src/Tile.cpp @@ -33,10 +33,14 @@ #include "hurricane/Instance.h" #include "hurricane/Vertical.h" #include "hurricane/Horizontal.h" +#include "hurricane/Diagonal.h" +#include "hurricane/Rectilinear.h" +#include "hurricane/Polygon.h" #include "hurricane/RoutingPad.h" #include "crlcore/Utilities.h" #include "tramontana/Tile.h" #include "tramontana/Equipotential.h" +#include "tramontana/SweepLine.h" namespace Tramontana { @@ -68,7 +72,10 @@ namespace Tramontana { using Hurricane::Entity; using Hurricane::Horizontal; using Hurricane::Vertical; - using Hurricane::RoutingPad; + using Hurricane::Vertical; + using Hurricane::Diagonal; + using Hurricane::Rectilinear; + using Hurricane::Polygon; using Hurricane::Cell; using Hurricane::Instance; @@ -82,14 +89,14 @@ namespace Tramontana { vector Tile::_allocateds; - Tile::Tile ( Occurrence occurrence, const BasicLayer* layer, const Box& boundingBox ) + Tile::Tile ( Occurrence occurrence, const BasicLayer* layer, const Box& boundingBox, Tile* parent ) : _id (_idCounter++) , _occurrence (occurrence) , _layer (layer) , _boundingBox (boundingBox) , _equipotential(nullptr) , _flags (0) - , _parent (nullptr) + , _parent (parent) , _rank (0) , _timeStamp (0) { @@ -97,7 +104,11 @@ namespace Tramontana { } - Tile* Tile::create ( Occurrence occurrence, const BasicLayer* layer ) + Tile* Tile::create ( Occurrence occurrence + , const BasicLayer* layer + , Tile* rootTile + , SweepLine* sweepLine + , uint32_t flags ) { Component* component = dynamic_cast( occurrence.getEntity() ); if (not component) { @@ -107,22 +118,72 @@ namespace Tramontana { ) << endl; return nullptr; } - if (not component->getLayer()->contains(layer)) { - cerr << Error( "Tile::create(): Component layer does not contains \"%s\".\n" + if (not (flags & ForceLayer) and not component->getLayer()->contains(layer)) { + cerr << "Intersect:" << component->getLayer()->getMask().intersect(layer->getMask()) << endl; + cerr << Error( "Tile::create(): Component layer \"%s\" does not contains \"%s\".\n" + " (%s)\n" + " component :%s\n" + " basicLayer:%s" + , getString(component->getLayer()->getName()).c_str() + , getString(layer->getName()).c_str() + , getString(occurrence).c_str() + , getString(component->getLayer()->getMask()).c_str() + , getString(layer->getMask()).c_str() + ) << endl; + return nullptr; + } + if (dynamic_cast(component)) { + cerr << Error( "Tile::create(): Polygon are not supported for extraction.\n" + " (%s)" + , getString(occurrence).c_str() + ) << endl; + return nullptr; + } + if (dynamic_cast(component)) { + cerr << Error( "Tile::create(): Diagonal are not supported for extraction.\n" " (%s)" - , getString(layer).c_str() , getString(occurrence).c_str() ) << endl; return nullptr; } + Occurrence childEqui = occurrence; + if (not childEqui.getPath().isEmpty()) + childEqui = Equipotential::getChildEqui( occurrence ); + + Rectilinear* rectilinear = dynamic_cast( component ); + if (rectilinear) { + if (not rectilinear->isRectilinear()) { + cerr << Error( "Tile::create(): Rectilinear with 45/135 edges are not supported for extraction.\n" + " (%s)" + , getString(occurrence).c_str() + ) << endl; + return nullptr; + } + if (rectilinear->getId() == 3367) { + DebugSession::open( 160, 169 ); + cdebug_log(160,0) << "Tiling: " << rectilinear << endl; + } + vector boxes; + rectilinear->getAsRectangles( boxes ); + for ( Box bb : boxes ) { + occurrence.getPath().getTransformation().applyOn( bb ); + Tile* tile = new Tile ( childEqui, layer, bb, rootTile ); + sweepLine->add( tile ); + cdebug_log(160,0) << "| " << tile << endl; + if (not rootTile) rootTile = tile; + } + if (rectilinear->getId() == 3367) { + DebugSession::close(); + } + return rootTile; + } + Box bb = component->getBoundingBox( layer ); occurrence.getPath().getTransformation().applyOn( bb ); - if (not occurrence.getPath().isEmpty()) - occurrence = Equipotential::getChildEqui( occurrence ); - Tile* tile = new Tile ( occurrence, layer, bb ); - + Tile* tile = new Tile ( childEqui, layer, bb, rootTile ); + sweepLine->add( tile ); return tile; } @@ -238,7 +299,8 @@ namespace Tramontana { string Tile::_getString () const { ostringstream os; - os << "getName() << " " << _occurrence << ">"; + os << "getName() << " " << _occurrence << ">"; return os.str(); } diff --git a/tramontana/src/tramontana/SweepLine.h b/tramontana/src/tramontana/SweepLine.h index b7f8be26..a7a4aec9 100644 --- a/tramontana/src/tramontana/SweepLine.h +++ b/tramontana/src/tramontana/SweepLine.h @@ -19,6 +19,7 @@ #pragma once #include #include +#include #include #include "hurricane/BasicLayer.h" namespace Hurricane { @@ -33,6 +34,7 @@ namespace Tramontana { using Hurricane::Record; using Hurricane::Box; using Hurricane::DbU; + using Hurricane::DBo; using Hurricane::Cell; using Hurricane::Layer; using Hurricane::BasicLayer; @@ -43,7 +45,10 @@ namespace Tramontana { class SweepLine { private: - typedef std::map IntervalTrees; + typedef std::map IntervalTrees; + public: + typedef std::set LayerSet; + typedef std::map ConnexityMap; private: class Element { public: @@ -66,6 +71,8 @@ namespace Tramontana { inline Cell* getCell (); inline const std::vector& getExtracteds () const; + inline Layer::Mask getExtractedMask () const; + const LayerSet& getCutConnexLayers ( const BasicLayer* ) const; void run (); void loadTiles (); inline void add ( Tile* ); @@ -76,9 +83,12 @@ namespace Tramontana { private: SweepLine ( const SweepLine& ) = delete; SweepLine& operator= ( const SweepLine& ) = delete; + void _buildCutConnexMap (); private: TramontanaEngine* _tramontana; std::vector _extracteds; + Layer::Mask _extractedsMask; + ConnexityMap _connexityMap; std::vector _tiles; IntervalTrees _intervalTrees; }; @@ -109,7 +119,8 @@ namespace Tramontana { // SweepLine. inline Cell* SweepLine::getCell () { return _tramontana->getCell(); } - inline const std::vector& SweepLine::getExtracteds () const { return _extracteds; } + inline const std::vector& SweepLine::getExtracteds () const { return _extracteds; } + inline Layer::Mask SweepLine::getExtractedMask () const { return _extractedsMask; } inline void SweepLine::add ( Tile* tile ) { diff --git a/tramontana/src/tramontana/Tile.h b/tramontana/src/tramontana/Tile.h index e316b0f5..2d2a3e20 100644 --- a/tramontana/src/tramontana/Tile.h +++ b/tramontana/src/tramontana/Tile.h @@ -44,6 +44,7 @@ namespace Tramontana { using Hurricane::IntervalData; using Hurricane::IntervalTree; class Equipotential; + class SweepLine; // ------------------------------------------------------------------- @@ -51,15 +52,20 @@ namespace Tramontana { 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); + 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); + static const uint32_t ForceLayer = (1<<4); public: static inline const std::vector getAllTiles (); static inline void timeTick (); - static Tile* create ( Occurrence, const BasicLayer* ); + static Tile* create ( Occurrence + , const BasicLayer* + , Tile* rootTile + , SweepLine* + , uint32_t flags=NoFlags ); void destroy (); inline bool isUpToDate () const; inline unsigned int getId () const; @@ -88,7 +94,7 @@ namespace Tramontana { std::string _getString () const; std::string _getTypeName () const; private: - Tile ( Occurrence, const BasicLayer*, const Box& ); + Tile ( Occurrence, const BasicLayer*, const Box&, Tile* parent ); ~Tile (); private: Tile ( const Tile& ) = delete; diff --git a/unittests/python/test_rectilinear.py b/unittests/python/test_rectilinear.py index 10b1db34..447dce17 100644 --- a/unittests/python/test_rectilinear.py +++ b/unittests/python/test_rectilinear.py @@ -48,7 +48,8 @@ def testRectilinear ( editor ): , Point( l( 20.0), l( 30.0) ) , Point( l( 30.0), l( 30.0) ) , Point( l( 30.0), l( 20.0) ) - , Point( l( 10.0), l( 0.0) ) ] + , Point( l( 10.0), l( 0.0) ) + , Point( l( 0.0), l( 0.0) ) ] r = Rectilinear.create( net, metal2, points ) #print( 'Normalized and manhattanized contour:' ) @@ -72,7 +73,9 @@ def testRectilinear ( editor ): # , Point( l( 90.0), l( 0.0) ) # 12 # , Point( l( 20.0), l( 0.0) ) # 13 # , Point( l( 20.0), l( 20.0) ) # 14 - # , Point( l( 0.0), l( 20.0) ) ] # 15 + # , Point( l( 0.0), l( 20.0) ) # 15 + # , Point( l( 0.0), l( 40.0) ) ] # 16 + # Super-test rectilinear. points = [ Point( l( 0.0), l( 0.0) ) # 0 , Point( l( 0.0), l( 20.0) ) # 1 , Point( l( 10.0), l( 20.0) ) # 2 @@ -83,7 +86,7 @@ def testRectilinear ( editor ): , Point( l( 40.0), l( 80.0) ) # 7 , Point( l( 20.0), l( 80.0) ) # 8 , Point( l( 20.0), l( 70.0) ) # 9 - + , Point( l( 10.0), l( 70.0) ) # 10 , Point( l( 10.0), l( 60.0) ) # 11 , Point( l( 0.0), l( 60.0) ) # 12 @@ -94,7 +97,7 @@ def testRectilinear ( editor ): , Point( l( 20.0), l(100.0) ) # 17 , Point( l( 40.0), l(100.0) ) # 18 , Point( l( 40.0), l(140.0) ) # 19 - + , Point( l( 20.0), l(140.0) ) # 20 , Point( l( 20.0), l(150.0) ) # 21 , Point( l( 10.0), l(150.0) ) # 22 @@ -105,7 +108,7 @@ def testRectilinear ( editor ): , Point( l( 40.0), l(170.0) ) # 27 , Point( l( 50.0), l(170.0) ) # 28 , Point( l( 50.0), l(160.0) ) # 29 - + , Point( l(150.0), l(160.0) ) # 30 , Point( l(150.0), l(150.0) ) # 31 , Point( l(130.0), l(150.0) ) # 32 @@ -116,7 +119,7 @@ def testRectilinear ( editor ): , Point( l(110.0), l(110.0) ) # 37 , Point( l(120.0), l(110.0) ) # 38 , Point( l(120.0), l(100.0) ) # 39 - + , Point( l(130.0), l(100.0) ) # 40 , Point( l(130.0), l( 90.0) ) # 41 , Point( l(150.0), l( 90.0) ) # 42 @@ -127,7 +130,7 @@ def testRectilinear ( editor ): , Point( l(110.0), l( 50.0) ) # 47 , Point( l(120.0), l( 50.0) ) # 48 , Point( l(120.0), l( 40.0) ) # 49 - + , Point( l(130.0), l( 40.0) ) # 50 , Point( l(130.0), l( 30.0) ) # 51 , Point( l(150.0), l( 30.0) ) # 52 @@ -135,7 +138,15 @@ def testRectilinear ( editor ): , Point( l( 50.0), l( 20.0) ) # 54 , Point( l( 50.0), l( 10.0) ) # 55 , Point( l( 40.0), l( 10.0) ) # 56 - , Point( l( 40.0), l( 0.0) ) ] # 57 + , Point( l( 40.0), l( 0.0) ) # 57 + , Point( l( 0.0), l( 0.0) ) ] # 57 + #points = [ Point( l( 0.0), l( 0.0) ) # 0 + # , Point( l( 0.0), l( 80.0) ) # 1 + # , Point( l( 40.0), l( 80.0) ) # 2 + # , Point( l( 40.0), l( 60.0) ) # 3 + # , Point( l( 20.0), l( 60.0) ) # 4 + # , Point( l( 20.0), l( 0.0) ) # 5 + # , Point( l( 0.0), l( 0.0) ) ] # 6 r = Rectilinear.create( net, metal2, points ) boxes = []