From 4f089ffdea43f300a7c9184389b4658045197a70 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 3 Jun 2018 11:47:31 +0200 Subject: [PATCH] Polygon internal normalization. Sub-polygons for GDSII driver. * Change: In Hurricane::Polygon, store the points so they are always ordered in the counter-clockwise (trigonometric) direction. This simplicificate internal computations. * New: In Hurricane::Polygon, added getSubPolygons() methods, that split horizontally the polygon in sub-polygons of about 1000 vertexes. This is mainly to be used by the GDSII driver to abide to the XY 4000 points limitation. * New: In Hurricane::Isobar, export support for Point collections so the various contour Polygon methods can be created in the Python interface. * New: In CRL::GdsDriver, split the Polygons into set of sub-polygons of less than 1000 vertexes. Use the getSubPolygons() method. * Change: In stratus1.dpgen_RF2, makes more explicit error messages about placement by displaying the faulty vs. expected coordinates. --- crlcore/src/ccore/gds/GdsDriver.cpp | 64 +++-- hurricane/src/hurricane/CMakeLists.txt | 2 +- hurricane/src/hurricane/Polygon.cpp | 238 +++++++++++++++++- hurricane/src/hurricane/Rectilinear.cpp | 3 + hurricane/src/hurricane/hurricane/Polygon.h | 4 +- hurricane/src/isobar/CMakeLists.txt | 2 + hurricane/src/isobar/PyComponent.cpp | 26 +- hurricane/src/isobar/PyHurricane.cpp | 4 + hurricane/src/isobar/PyPointCollection.cpp | 76 ++++++ hurricane/src/isobar/PyPolygon.cpp | 22 ++ .../hurricane/isobar/PyPointCollection.h | 59 +++++ hurricane/src/viewer/CellImage.cpp | 2 +- hurricane/src/viewer/CellWidget.cpp | 11 + stratus1/src/dpgen/dpgen_RF2.py | 2 +- stratus1/src/stratus/st_placement.py | 20 +- stratus1/src/stratus/util_Place.py | 7 +- 16 files changed, 499 insertions(+), 43 deletions(-) create mode 100644 hurricane/src/isobar/PyPointCollection.cpp create mode 100644 hurricane/src/isobar/hurricane/isobar/PyPointCollection.h diff --git a/crlcore/src/ccore/gds/GdsDriver.cpp b/crlcore/src/ccore/gds/GdsDriver.cpp index 55517178..ff91da65 100644 --- a/crlcore/src/ccore/gds/GdsDriver.cpp +++ b/crlcore/src/ccore/gds/GdsDriver.cpp @@ -30,6 +30,8 @@ using namespace std; #include "hurricane/Horizontal.h" #include "hurricane/Vertical.h" #include "hurricane/Diagonal.h" +#include "hurricane/Rectilinear.h" +#include "hurricane/Polygon.h" #include "hurricane/Pad.h" #include "hurricane/Net.h" #include "hurricane/Cell.h" @@ -338,6 +340,7 @@ namespace { GdsStream& operator<< ( const BasicLayer* ); GdsStream& operator<< ( const Box& ); GdsStream& operator<< ( const Points ); + GdsStream& operator<< ( const vector& points ); GdsStream& operator<< ( const Cell* ); GdsStream& operator<< ( const Transformation& ); private: @@ -513,6 +516,20 @@ namespace { } + GdsStream& GdsStream::operator<< ( const vector& points ) + { + GdsRecord record ( GdsRecord::XY ); + for ( Point p : points ) { + record.push( (int32_t)DbU::toGrid(p.getX()) ); + record.push( (int32_t)DbU::toGrid(p.getY()) ); + } + record.push( (int32_t)DbU::toGrid(points[0].getX()) ); + record.push( (int32_t)DbU::toGrid(points[0].getY()) ); + _ostream << record; + return *this; + } + + GdsStream& GdsStream::operator<< ( const Cell* cell ) { time_t t = time( 0 ); @@ -546,23 +563,38 @@ namespace { for ( Net* net : cell->getNets() ) { for ( Component* component : net->getComponents() ) { - Diagonal* diagonal = dynamic_cast(component); - if (diagonal) { - for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { - (*this) << BOUNDARY; - (*this) << layer; - (*this) << diagonal->getContour(); - (*this) << ENDEL; + Polygon* polygon = dynamic_cast(component); + if (polygon) { + vector< vector > subpolygons; + polygon->getSubPolygons( subpolygons ); + + for ( const vector& subpolygon : subpolygons ) { + for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { + (*this) << BOUNDARY; + (*this) << layer; + (*this) << subpolygon; + (*this) << ENDEL; + } } - } else if ( dynamic_cast(component) - or dynamic_cast(component) - or dynamic_cast(component) - or dynamic_cast(component)) { - for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { - (*this) << BOUNDARY; - (*this) << layer; - (*this) << component->getBoundingBox(layer); - (*this) << ENDEL; + } else { + Diagonal* diagonal = dynamic_cast(component); + if (diagonal) { + for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { + (*this) << BOUNDARY; + (*this) << layer; + (*this) << diagonal->getContour(); + (*this) << ENDEL; + } + } else if ( dynamic_cast(component) + or dynamic_cast(component) + or dynamic_cast(component) + or dynamic_cast(component)) { + for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { + (*this) << BOUNDARY; + (*this) << layer; + (*this) << component->getBoundingBox(layer); + (*this) << ENDEL; + } } } } diff --git a/hurricane/src/hurricane/CMakeLists.txt b/hurricane/src/hurricane/CMakeLists.txt index 09c4c720..013c1534 100644 --- a/hurricane/src/hurricane/CMakeLists.txt +++ b/hurricane/src/hurricane/CMakeLists.txt @@ -94,7 +94,7 @@ hurricane/Technology.h hurricane/Timer.h hurricane/Transformation.h - hurricane/Polygon.h + hurricane/Polygon.h hurricane/Polygons.h hurricane/DbU.h hurricane/UpdateSession.h hurricane/VectorCollection.h diff --git a/hurricane/src/hurricane/Polygon.cpp b/hurricane/src/hurricane/Polygon.cpp index e832bad0..80672571 100644 --- a/hurricane/src/hurricane/Polygon.cpp +++ b/hurricane/src/hurricane/Polygon.cpp @@ -85,8 +85,8 @@ namespace Hurricane { DbU::Unit m = y % DbU::getPolygonStep(); if (m) { - if (isClockwise() xor not isXIncrease()) y += DbU::getPolygonStep() - m; - else y += -m; + if (not isXIncrease()) y += DbU::getPolygonStep() - m; + else y += -m; } _steps.push_back( y ); @@ -111,8 +111,8 @@ namespace Hurricane { DbU::Unit m = x % DbU::getPolygonStep(); if (m) { - if (isClockwise() xor isYIncrease()) x += DbU::getPolygonStep() - m; - else x += -m; + if (isYIncrease()) x += DbU::getPolygonStep() - m; + else x += -m; } _steps.push_back( x ); @@ -132,7 +132,6 @@ namespace Hurricane { Point point; - if (_flags & YSteps) { DbU::Unit delta = DbU::getPolygonStep(); if (not (_flags & Polygon::YIncrease)) delta = -delta; @@ -219,7 +218,28 @@ namespace Hurricane { sign = nextSign; } - Polygon* triangle = new Polygon ( net, layer, points ); + size_t istart = 0; + for ( size_t i=0 ; i points[istart].getX()) + or ( (points[i].getX() == points[istart].getX()) + and (points[i].getY() > points[istart].getY()) ) ) + istart = i; + } + + vector normalized ( points.size(), Point() ); + if ( (istart != 0) or (sign > 0.0) ) { + if (sign < 0.0) { + for ( size_t i=0 ; i_postCreate(); triangle->manhattanize(); return triangle; @@ -368,19 +388,217 @@ namespace Hurricane { for ( Edge* edge : _edges ) delete edge; _edges.clear(); - bool clockwise = (getSign(_points,0) <= 0); - for ( size_t i=0 ; i<_points.size() ; ++i ) { const Point& origin = _points[ i % _points.size()]; const Point& extremity = _points[ (i+1) % _points.size()]; bool dxPositive = (extremity.getX() > origin.getX()); - uint32_t flags = (clockwise xor dxPositive) ? 0 : Above; - flags |= (clockwise) ? Clockwise : 0; + uint32_t flags = (dxPositive) ? 0 : Above; _edges.push_back( new Edge ( origin, extremity, flags ) ); } } + + void Polygon::getSubPolygons ( vector< vector >& subpolygons ) const + { + static const size_t subPolygonSize = 1000; + + // cerr << "Polygon::getSubPolygons(): " << this << endl; + + vector upSide; + vector downSide; + Point first; + + bool firstToDown = false; + bool inUpSide = true; + for ( Point p : getMContour() ) { + // cerr << "| " << p << endl; + + if (upSide.size() == 1) { + if (upSide[0].getX() == p.getX()) { + if (not firstToDown) { firstToDown = true; first = upSide[0]; } + upSide.pop_back(); + } + } + + if (inUpSide and not upSide.empty()) { + if (upSide.back().getX() < p.getX()) { + inUpSide = false; + // cerr << "Switch to down side." << endl; + } + } + + if (inUpSide) { + size_t length = upSide.size(); + if ( (length > 1) + and ( ( (upSide[length-2].getX() == upSide[length-1].getX()) and (upSide.back().getX() == p.getX()) ) + or ( (upSide[length-2].getY() == upSide[length-1].getY()) and (upSide.back().getY() == p.getY()) ) ) ) { + upSide.pop_back(); + } + upSide.push_back( p ); + } else { + size_t length = downSide.size(); + if ( (length > 1) + and ( ( (downSide[length-2].getX() == downSide[length-1].getX()) and (downSide.back().getX() == p.getX()) ) + or ( (downSide[length-2].getY() == downSide[length-1].getY()) and (downSide.back().getY() == p.getY()) ) ) ) { + downSide.pop_back(); + } + + if (downSide.empty()) { + downSide.push_back( upSide.back() ); + upSide.pop_back(); + } + downSide.push_back( p ); + } + } + + std::reverse( upSide.begin(), upSide.end() ); + + // cerr << "firstToDown:" << firstToDown << endl; + if (firstToDown and (first.getX() > downSide.back().getX())) downSide.push_back( first ); + while ( downSide.size() > 1 ) { + size_t length = downSide.size()-1; + if (downSide[length-1].getX() != downSide[length].getX()) break; + downSide.pop_back(); + } + + // cerr << "Up side" << endl; + // for ( size_t i=0 ; i* polygon = NULL; + size_t startUp = 0; + size_t startDown = 0; + size_t stopUp = 1; + size_t stopDown = 1; + + while ( true ) { + size_t leftCutUp = 0; + size_t leftCutDown = 0; + size_t rightCutUp = 0; + size_t rightCutDown = 0; + size_t downIncrease = 0; + size_t upDecrease = 0; + + if (stopUp - startUp + stopDown - startDown > subPolygonSize) { + // carve out a new sub-polygon-> + // cerr << "New sub polygon:" << endl; + // cerr << " stopUp:" << setw(3) << stopUp << " startUp:" << setw(3) << startUp << endl; + // cerr << " stopDown:" << setw(3) << stopDown << " startDown:" << setw(3) << startDown << endl; + + subpolygons.push_back( vector() ); + polygon = &subpolygons.back(); + + if (upSide[startUp].getX() > downSide[startDown].getX()) { + polygon->push_back( Point( downSide[startDown].getX(), upSide[startUp].getY() ) ); + // cerr << " + " << polygon->back() << endl; + leftCutUp = 1; + } else { + if (upSide[startUp].getX() < downSide[startDown].getX()) { + polygon->push_back( Point( upSide[startUp].getX(), downSide[startDown].getY() ) ); + // cerr << " + " << polygon->back() << endl; + leftCutDown = 1; + } + } + + if (upSide[stopUp].getX() > downSide[stopDown].getX()) rightCutUp = 1; + else if (upSide[stopUp].getX() < downSide[stopDown].getX()) rightCutDown = 1; + + if (not leftCutDown and (downSide[startDown+1].getY() > downSide[startDown].getY())) downIncrease = 1; + + for ( size_t i=startDown+downIncrease ; i<=stopDown-rightCutDown ; ++i ) { + polygon->push_back( downSide[i] ); + // cerr << " > " << polygon->back() << endl; + } + + if (rightCutUp) { + polygon->push_back( Point( downSide[stopDown].getX(), upSide[stopUp].getY() ) ); + // cerr << " + " << polygon->back() << endl; + } else { + if (rightCutDown) { + polygon->push_back( Point( upSide[stopUp].getX(), downSide[stopDown].getY() ) ); + // cerr << " + " << polygon->back() << endl; + // cerr << " Adjust down (cut)" << endl; + } + } + + if (not leftCutUp and (upSide[startUp+1].getY() < upSide[startUp].getY())) upDecrease = 1; + + for ( size_t i=rightCutUp ; i<=stopUp-startUp-upDecrease ; ++i ) { + polygon->push_back( upSide[stopUp-i] ); + // cerr << " < " << polygon->back() << endl; + } + + startUp = stopUp; + startDown = stopDown; + + // cerr << "Done sub polygon." << endl; + } + + if (upSide[stopUp].getX() == downSide[stopDown].getX()) { + stopUp += 2; + stopDown += 2; + } else { + if (upSide[stopUp].getX() < downSide[stopDown].getX()) stopUp += 2; + else stopDown += 2; + } + stopUp = std::min( stopUp , upSide.size()-1 ); + stopDown = std::min( stopDown, downSide.size()-1 ); + + // cerr << " stopUp:" << stopUp << " stopDown:" << stopDown << endl; + + if ( (stopUp+5 > upSide.size()) and (stopDown+5 > downSide.size()) ) { + stopUp = upSide.size() - 1; + stopDown = downSide.size() - 1; + break; + } + } + + subpolygons.push_back( vector() ); + polygon = &subpolygons.back(); + + // cerr << "Last (right) sub polygon:" << endl; + // cerr << " stopUp:" << setw(3) << stopUp << " startUp:" << setw(3) << startUp << endl; + // cerr << " stopDown:" << setw(3) << stopDown << " startDown:" << setw(3) << startDown << endl; + + size_t downIncrease = 0; + size_t upDecrease = 0; + size_t leftCutUp = 0; + size_t leftCutDown = 0; + + if (upSide[startUp].getX() > downSide[startDown].getX()) { + polygon->push_back( Point( downSide[startDown].getX(), upSide[startUp].getY() ) ); + // cerr << " + " << polygon->back() << endl; + leftCutUp = 1; + } else { + if (upSide[startUp].getX() < downSide[startDown].getX()) { + polygon->push_back( Point( upSide[startUp].getX(), downSide[startDown].getY() ) ); + // cerr << " + " << polygon->back() << endl; + leftCutDown = 1; + } + } + + if (not leftCutDown and (downSide[startDown+1].getY() > downSide[startDown].getY())) downIncrease = 1; + + for ( size_t i=startDown+downIncrease ; i<=stopDown ; ++i ) { + polygon->push_back( downSide[i] ); + // cerr << " > " << polygon->back() << endl; + } + + if (not leftCutUp and (upSide[startUp+1].getY() < upSide[startUp].getY())) upDecrease = 1; + + for ( size_t i=0 ; i<=stopUp-startUp-upDecrease ; ++i ) { + polygon->push_back( upSide[stopUp-i] ); + // cerr << " < " << polygon->back() << endl; + } + + // cerr << endl; + } + void Polygon::_toJson ( JsonWriter* writer ) const { diff --git a/hurricane/src/hurricane/Rectilinear.cpp b/hurricane/src/hurricane/Rectilinear.cpp index 68d21855..de8109c3 100644 --- a/hurricane/src/hurricane/Rectilinear.cpp +++ b/hurricane/src/hurricane/Rectilinear.cpp @@ -56,6 +56,9 @@ namespace Hurricane { if (not layer) throw Error( "Rectilinear::create(): Can't create, NULL layer" ); + if (points.size() > 1000) + throw Error( "Rectilinear::create(): Rectlinear polygons must not exceed 1000 vertexes." ); + for ( size_t i=0 ; i >& ) const; virtual const Layer* getLayer () const; void setLayer ( const Layer* layer ); virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy ); @@ -144,7 +143,6 @@ namespace Hurricane { inline const vector& Polygon::getEdges () const { return _edges; } inline const vector& Polygon::getPoints () const { return _points; } - inline bool Polygon::Edge::isClockwise () const { return (_flags & Polygon::Clockwise); } inline bool Polygon::Edge::isYIncrease () const { return (_flags & Polygon::YIncrease); } inline bool Polygon::Edge::isXIncrease () const { return (_flags & Polygon::XIncrease); } inline bool Polygon::Edge::isPositiveSlope () const { return not ( (_flags & Polygon::XIncrease) xor (_flags & Polygon::YIncrease) ); } diff --git a/hurricane/src/isobar/CMakeLists.txt b/hurricane/src/isobar/CMakeLists.txt index 5a078754..6ee2c4a1 100644 --- a/hurricane/src/isobar/CMakeLists.txt +++ b/hurricane/src/isobar/CMakeLists.txt @@ -60,6 +60,7 @@ PyPlug.cpp PyPlugCollection.cpp PyPoint.cpp + PyPointCollection.cpp PyReference.cpp PyReferenceCollection.cpp PyRoutingPad.cpp @@ -129,6 +130,7 @@ hurricane/isobar/PyPlug.h hurricane/isobar/PyPlugCollection.h hurricane/isobar/PyPoint.h + hurricane/isobar/PyPointCollection.h hurricane/isobar/PyReference.h hurricane/isobar/PyReferenceCollection.h hurricane/isobar/PyRoutingPad.h diff --git a/hurricane/src/isobar/PyComponent.cpp b/hurricane/src/isobar/PyComponent.cpp index ed481a2a..1910e6f3 100644 --- a/hurricane/src/isobar/PyComponent.cpp +++ b/hurricane/src/isobar/PyComponent.cpp @@ -26,6 +26,7 @@ #include "hurricane/isobar/PyVertical.h" #include "hurricane/isobar/PyContact.h" #include "hurricane/isobar/PyPin.h" +#include "hurricane/isobar/PyPointCollection.h" #include "hurricane/isobar/PyComponentCollection.h" @@ -196,6 +197,26 @@ extern "C" { } + static PyObject* PyComponent_getContour ( PyComponent *self ) + { + cdebug_log(20,0) << "PyComponent_getContour()" << endl; + METHOD_HEAD( "Component.getContour()" ) + + PyPointCollection* pyPointCollection = NULL; + + HTRY + Points* points = new Points( component->getContour() ); + + pyPointCollection = PyObject_NEW(PyPointCollection, &PyTypePointCollection); + if (pyPointCollection == NULL) return NULL; + + pyPointCollection->_object = points; + HCATCH + + return (PyObject*)pyPointCollection; + } + + PyMethodDef PyComponent_Methods[] = { { "getBodyHook" , (PyCFunction)PyComponent_getBodyHook , METH_NOARGS , "Return the component body hook (is a master Hook)." } , { "getX" , (PyCFunction)PyComponent_getX , METH_NOARGS , "Return the Component X value." } @@ -205,8 +226,9 @@ extern "C" { , { "getNet" , (PyCFunction)PyComponent_getNet , METH_NOARGS , "Returns the net owning the component." } , { "getLayer" , (PyCFunction)PyComponent_getLayer , METH_NOARGS , "Return the component layer." } , { "getBoundingBox" , (PyCFunction)PyComponent_getBoundingBox , METH_VARARGS, "Return the component boundingBox (optionally on a BasicLayer)." } - , { "getConnexComponents" , (PyCFunction)PyComponent_getConnexComponents, METH_NOARGS, "All the components connecteds to this one through hyper hooks." } - , { "getSlaveComponents" , (PyCFunction)PyComponent_getSlaveComponents , METH_NOARGS, "All the components anchored directly or indirectly on this one." } + , { "getContour" , (PyCFunction)PyComponent_getContour , METH_NOARGS , "Return the points of the polygonic contour." } + , { "getConnexComponents" , (PyCFunction)PyComponent_getConnexComponents, METH_NOARGS , "All the components connecteds to this one through hyper hooks." } + , { "getSlaveComponents" , (PyCFunction)PyComponent_getSlaveComponents , METH_NOARGS , "All the components anchored directly or indirectly on this one." } , { "destroy" , (PyCFunction)PyComponent_destroy , METH_NOARGS , "destroy associated hurricane object, the python object remains." } , {NULL, NULL, 0, NULL} /* sentinel */ diff --git a/hurricane/src/isobar/PyHurricane.cpp b/hurricane/src/isobar/PyHurricane.cpp index a3e0aff4..a2e05fb1 100644 --- a/hurricane/src/isobar/PyHurricane.cpp +++ b/hurricane/src/isobar/PyHurricane.cpp @@ -20,6 +20,7 @@ #include "hurricane/isobar/PyUpdateSession.h" #include "hurricane/isobar/PyDbU.h" #include "hurricane/isobar/PyPoint.h" +#include "hurricane/isobar/PyPointCollection.h" #include "hurricane/isobar/PyInterval.h" #include "hurricane/isobar/PyBox.h" #include "hurricane/isobar/PyTransformation.h" @@ -517,6 +518,7 @@ extern "C" { PyUpdateSession_LinkPyType (); PyDbU_LinkPyType (); PyPoint_LinkPyType (); + PyPointCollection_LinkPyType (); PyInterval_LinkPyType (); PyBox_LinkPyType (); PyTransformation_LinkPyType (); @@ -584,6 +586,7 @@ extern "C" { PYTYPE_READY ( UpdateSession ) PYTYPE_READY ( DbU ) PYTYPE_READY ( Point ) + PYTYPE_READY ( PointCollection ) PYTYPE_READY ( Interval ) PYTYPE_READY ( Box ) PYTYPE_READY ( Transformation ) @@ -709,6 +712,7 @@ extern "C" { __cs.addType ( "plug" , &PyTypePlug , "" , false, "comp" ); __cs.addType ( "plugCol" , &PyTypePlugCollection , "" , false ); __cs.addType ( "point" , &PyTypePoint , "" , false ); + __cs.addType ( "points" , &PyTypePointCollection , "" , false ); __cs.addType ( "rp" , &PyTypeRoutingPad , "" , false, "comp" ); __cs.addType ( "segment" , &PyTypeSegment , "" , false, "comp" ); __cs.addType ( "pad " , &PyTypePad , "" , false, "comp" ); diff --git a/hurricane/src/isobar/PyPointCollection.cpp b/hurricane/src/isobar/PyPointCollection.cpp new file mode 100644 index 00000000..3317cf61 --- /dev/null +++ b/hurricane/src/isobar/PyPointCollection.cpp @@ -0,0 +1,76 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyPointCollection.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/isobar/PyPointCollection.h" +#include "hurricane/isobar/PyPoint.h" + +namespace Isobar { + +using namespace Hurricane; + + extern "C" { + + +// +=================================================================+ +// | "PyPointCollection" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + + DirectDeleteMethod(PyPointCollection_DeAlloc, PyPointCollection) + + + static PyObject* PyPointLocatorNext ( PyPointCollectionLocator* pyLocator ) + { + Locator* locator = pyLocator->_object; + + HTRY + if (locator->isValid()) { + Point point = locator->getElement(); + PyPoint* pyPoint = PyObject_NEW(PyPoint, &PyTypePoint); + if (pyPoint == NULL) return NULL; + pyPoint->_object = new Point(point); + + locator->progress(); + return (PyObject*)pyPoint; + } + HCATCH + return NULL; + } + + + CollectionMethods(Point) + + +#else // Python Module Code Part. + + +// +=================================================================+ +// | "PyPointCollection" Shared Library Code Part | +// +=================================================================+ + + + PyTypeCollectionObjectDefinitions(PointCollection) + PyTypeCollectionObjectDefinitions(PointCollectionLocator) + + +#endif // Shared Library Code Part. + + + } // extern "C". + +} // Isobar namespace. diff --git a/hurricane/src/isobar/PyPolygon.cpp b/hurricane/src/isobar/PyPolygon.cpp index 78376739..8e697792 100644 --- a/hurricane/src/isobar/PyPolygon.cpp +++ b/hurricane/src/isobar/PyPolygon.cpp @@ -15,6 +15,7 @@ #include "hurricane/isobar/PyPoint.h" +#include "hurricane/isobar/PyPointCollection.h" #include "hurricane/isobar/PyNet.h" #include "hurricane/isobar/PyLayer.h" #include "hurricane/isobar/PyBox.h" @@ -169,6 +170,26 @@ extern "C" { } + static PyObject* PyPolygon_getMContour ( PyPolygon *self ) + { + cdebug_log(20,0) << "PyPolygon_getMContour()" << endl; + METHOD_HEAD( "Polygon.getMContour()" ) + + PyPointCollection* pyPointCollection = NULL; + + HTRY + Points* points = new Points( polygon->getMContour() ); + + pyPointCollection = PyObject_NEW(PyPointCollection, &PyTypePointCollection); + if (pyPointCollection == NULL) return NULL; + + pyPointCollection->_object = points; + HCATCH + + return (PyObject*)pyPointCollection; + } + + // --------------------------------------------------------------- // PyPolygon Attribute Method table. @@ -178,6 +199,7 @@ extern "C" { , { "getX" , (PyCFunction)PyPolygon_getX , METH_NOARGS , "Return the Polygon X value." } , { "getY" , (PyCFunction)PyPolygon_getY , METH_NOARGS , "Return the Polygon Y value." } , { "getBoundingBox", (PyCFunction)PyPolygon_getBoundingBox, METH_NOARGS , "Return the Polygon Bounding Box." } + , { "getMContour" , (PyCFunction)PyPolygon_getMContour , METH_NOARGS , "Return the points of the manhattanized contour." } , { "setPoints" , (PyCFunction)PyPolygon_setPoints , METH_VARARGS, "Sets the Polygon Bounding Box." } , { "translate" , (PyCFunction)PyPolygon_translate , METH_VARARGS, "Translates the Polygon of dx and dy." } , { "destroy" , (PyCFunction)PyPolygon_destroy , METH_NOARGS diff --git a/hurricane/src/isobar/hurricane/isobar/PyPointCollection.h b/hurricane/src/isobar/hurricane/isobar/PyPointCollection.h new file mode 100644 index 00000000..401d3c28 --- /dev/null +++ b/hurricane/src/isobar/hurricane/isobar/PyPointCollection.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2018-2018, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/isobar/PyPointCollection.h" | +// +-----------------------------------------------------------------+ + + +#ifndef PY_POINT_COLLECTION_H +#define PY_POINT_COLLECTION_H + +#include "hurricane/isobar/PyHurricane.h" +#include "hurricane/Point.h" +#include "hurricane/Points.h" + + +namespace Isobar { + + + extern "C" { + + +// ------------------------------------------------------------------- +// Python Object : "PyPointCollection". + + typedef struct { + PyObject_HEAD + Hurricane::Points* _object; + } PyPointCollection; + + typedef struct { + PyObject_HEAD + Hurricane::Locator* _object; + PyPointCollection* _collection; + } PyPointCollectionLocator; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.ccp". + + extern PyTypeObject PyTypePointCollection; + extern PyTypeObject PyTypePointCollectionLocator; + + extern void PyPointCollection_LinkPyType(); + extern void PyPointCollectionLocator_LinkPyType(); + + } // extern "C". + +} // Isobar namespace. + +#endif // PY_POINT_COLLECTION_H diff --git a/hurricane/src/viewer/CellImage.cpp b/hurricane/src/viewer/CellImage.cpp index 184e54c7..cd342014 100644 --- a/hurricane/src/viewer/CellImage.cpp +++ b/hurricane/src/viewer/CellImage.cpp @@ -127,7 +127,7 @@ namespace Hurricane { _flags = flags; //int scale = 80 * Cfg::getParamEnumerate("viewer.printer.mode")->asInt(); - int scale = (Graphics::isHighDpi()) ? 1 : 2; + int scale = (Graphics::isHighDpi()) ? 4 : 2; _drawingWidth = _cellWidget->width () * scale; _drawingHeight = _cellWidget->height() * scale; diff --git a/hurricane/src/viewer/CellWidget.cpp b/hurricane/src/viewer/CellWidget.cpp index 57a2937c..2814b957 100644 --- a/hurricane/src/viewer/CellWidget.cpp +++ b/hurricane/src/viewer/CellWidget.cpp @@ -685,6 +685,17 @@ namespace Hurricane { for ( Point point : component->getMContour() ) contour << _cellWidget->dbuToScreenPoint( point ); _cellWidget->drawScreenPolygon( contour ); + + // const Polygon* polygon = dynamic_cast( component ); + // if (polygon) { + // vector< vector > subpolygons; + // polygon->getSubPolygons( subpolygons ); + // for ( const vector& sp : subpolygons ) { + // contour.clear(); + // for ( Point point : sp ) contour << _cellWidget->dbuToScreenPoint( point ); + // _cellWidget->drawScreenPolygon( contour ); + // } + // } } } return; diff --git a/stratus1/src/dpgen/dpgen_RF2.py b/stratus1/src/dpgen/dpgen_RF2.py index 1a85fe3b..b8f2e15f 100644 --- a/stratus1/src/dpgen/dpgen_RF2.py +++ b/stratus1/src/dpgen/dpgen_RF2.py @@ -940,7 +940,7 @@ class top_rf2 ( Model ) : global adrange #HCELL = 50 - HCELL = DbU.toLambda( self.In[0]._hur_masterCell.getAbutmentBox().getHeight() ) + HCELL = self.In[0]._hur_masterCell.getAbutmentBox().getHeight() # placement des lignes de bit en dessous des buffers bottom = 0 diff --git a/stratus1/src/stratus/st_placement.py b/stratus1/src/stratus/st_placement.py index 09f630c7..86371dd9 100644 --- a/stratus1/src/stratus/st_placement.py +++ b/stratus1/src/stratus/st_placement.py @@ -64,10 +64,12 @@ def Place ( ins, sym, ref, plac = FIXED, cell = None ) : if ref._x % MYPITCH : err = "\n[Stratus ERROR] Place : " + ins._name + " : coordinate x is not a mutiple of PITCH.\n" raise Exception ( err ) - + if ref._y % MYSLICE : - err = "\n[Stratus ERROR] Place : " + ins._name + " : coordinate y is not a mutiple of SLICE.\n" - raise Exception ( err ) + message = '\n[ERROR] Stratus.Model.Place(): For instance "' \ + + ins._name + '", coordinate Y ' + DbU.getValueString(ref._y) + ' (' + str(ref._y) + ')' \ + + " is not a mutiple of slice " + DbU.getValueString(MYSLICE) + '.' + raise Exception( message ) # Error message : if ref is not a reference if str ( ref.__class__ ) != "st_ref.XY" : @@ -127,12 +129,16 @@ def PlaceRight ( ins, symetry, offsetX = 0, offsetY = 0, plac = FIXED ) : cell = CELLS[-1] if offsetX % MYPITCH : - err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : offsetX is not a mutiple of PITCH.\n" - raise Exception ( err ) + message = '\n[ERROR] Stratus.Model.PlaceRight(): For instance "' \ + + ins._name + '", offsetX ' + DbU.getValueString(offsetX) \ + + " is not a mutiple of pitch " + DbU.getValueString(MYPITCH) + '.' + raise Exception( message ) if offsetY % MYSLICE : - err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : offsetY is not a mutiple of SLICE.\n" - raise Exception ( err ) + message = '\n[ERROR] Stratus.Model.PlaceRight(): For instance "' \ + + ins._name + '", offsetY ' + DbU.getValueString(offsetX) \ + + " is not a mutiple of slice " + DbU.getValueString(MYSLICE) + '.' + raise Exception( message ) if ( plac != PLACED ) and ( plac != FIXED ) : err = "\n[Stratus ERROR] PlaceRight : " + ins._name + " : wrong argument for placement type.\n" diff --git a/stratus1/src/stratus/util_Place.py b/stratus1/src/stratus/util_Place.py index 43421564..084a313e 100644 --- a/stratus1/src/stratus/util_Place.py +++ b/stratus1/src/stratus/util_Place.py @@ -47,6 +47,9 @@ # x-----------------------------------------------------------------x +from Hurricane import DbU + + NOSYM = 1000 SYM_X = 1001 SYM_Y = 1002 @@ -66,5 +69,5 @@ SOUTH = 1022 EAST = 1023 WEST = 1024 -MYPITCH = 5 -MYSLICE = 50 +MYPITCH = DbU.fromLambda( 5.0 ) +MYSLICE = DbU.fromLambda( 50.0 )