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.
This commit is contained in:
Jean-Paul Chaput 2018-06-03 11:47:31 +02:00
parent ea16b5a556
commit 4f089ffdea
16 changed files with 499 additions and 43 deletions

View File

@ -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<Point>& points );
GdsStream& operator<< ( const Cell* );
GdsStream& operator<< ( const Transformation& );
private:
@ -513,6 +516,20 @@ namespace {
}
GdsStream& GdsStream::operator<< ( const vector<Point>& 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,6 +563,20 @@ namespace {
for ( Net* net : cell->getNets() ) {
for ( Component* component : net->getComponents() ) {
Polygon* polygon = dynamic_cast<Polygon*>(component);
if (polygon) {
vector< vector<Point> > subpolygons;
polygon->getSubPolygons( subpolygons );
for ( const vector<Point>& subpolygon : subpolygons ) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
(*this) << BOUNDARY;
(*this) << layer;
(*this) << subpolygon;
(*this) << ENDEL;
}
}
} else {
Diagonal* diagonal = dynamic_cast<Diagonal*>(component);
if (diagonal) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
@ -567,6 +598,7 @@ namespace {
}
}
}
}
(*this) << ENDSTR;

View File

@ -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

View File

@ -85,7 +85,7 @@ namespace Hurricane {
DbU::Unit m = y % DbU::getPolygonStep();
if (m) {
if (isClockwise() xor not isXIncrease()) y += DbU::getPolygonStep() - m;
if (not isXIncrease()) y += DbU::getPolygonStep() - m;
else y += -m;
}
_steps.push_back( y );
@ -111,7 +111,7 @@ namespace Hurricane {
DbU::Unit m = x % DbU::getPolygonStep();
if (m) {
if (isClockwise() xor isYIncrease()) x += DbU::getPolygonStep() - 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.size() ; ++i ) {
if ( (points[i].getX() > points[istart].getX())
or ( (points[i].getX() == points[istart].getX())
and (points[i].getY() > points[istart].getY()) ) )
istart = i;
}
vector<Point> normalized ( points.size(), Point() );
if ( (istart != 0) or (sign > 0.0) ) {
if (sign < 0.0) {
for ( size_t i=0 ; i<points.size() ; ++i )
normalized[ (points.size()-i) % points.size() ] = points[ (istart+i) % points.size() ];
} else {
for ( size_t i=0 ; i<points.size() ; ++i )
normalized[ i ] = points[ (istart+i) % points.size() ];
}
} else
normalized = points;
Polygon* triangle = new Polygon ( net, layer, normalized );
triangle->_postCreate();
triangle->manhattanize();
return triangle;
@ -368,20 +388,218 @@ 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<Point> >& subpolygons ) const
{
static const size_t subPolygonSize = 1000;
// cerr << "Polygon::getSubPolygons(): " << this << endl;
vector<Point> upSide;
vector<Point> 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<upSide.size() ; ++i )
// cerr << "[ " << setw(3) << i << "] " << upSide[i] << endl;
// cerr << "Down side" << endl;
// for ( size_t i=0 ; i<downSide.size() ; ++i )
// cerr << "[ " << setw(3) << i << "] " << downSide[i] << endl;
vector<Point>* 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<Point>() );
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<Point>() );
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
{
Super::_toJson( writer );

View File

@ -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<points.size() ; ++i ) {
size_t j = (i+1) % points.size();

View File

@ -52,7 +52,6 @@ namespace Hurricane {
static const uint32_t YIncrease = (1<<4);
static const uint32_t Horizontal = (1<<5);
static const uint32_t Vertical = (1<<6);
static const uint32_t Clockwise = (1<<7);
public:
class Edge {
@ -61,7 +60,6 @@ namespace Hurricane {
inline size_t getSize () const;
Point getPoint ( size_t i ) const;
inline bool isPositiveSlope () const;
inline bool isClockwise () const;
inline bool isYIncrease () const;
inline bool isXIncrease () const;
inline bool isHV () const;
@ -118,6 +116,7 @@ namespace Hurricane {
virtual Point getPoint ( size_t ) const;
virtual Box getBoundingBox () const;
virtual Box getBoundingBox ( const BasicLayer* ) const;
void getSubPolygons ( vector< vector<Point> >& ) 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::Edge*>& Polygon::getEdges () const { return _edges; }
inline const vector<Point>& 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) ); }

View File

@ -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

View File

@ -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,6 +226,7 @@ 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)." }
, { "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

View File

@ -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 , "<Plug>" , false, "comp" );
__cs.addType ( "plugCol" , &PyTypePlugCollection , "<PlugCollection>" , false );
__cs.addType ( "point" , &PyTypePoint , "<Point>" , false );
__cs.addType ( "points" , &PyTypePointCollection , "<Points>" , false );
__cs.addType ( "rp" , &PyTypeRoutingPad , "<RoutingPad>" , false, "comp" );
__cs.addType ( "segment" , &PyTypeSegment , "<Segment>" , false, "comp" );
__cs.addType ( "pad " , &PyTypePad , "<Pad>" , false, "comp" );

View File

@ -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<Point>* 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.

View File

@ -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

View File

@ -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<Hurricane::Point>* _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

View File

@ -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;

View File

@ -685,6 +685,17 @@ namespace Hurricane {
for ( Point point : component->getMContour() )
contour << _cellWidget->dbuToScreenPoint( point );
_cellWidget->drawScreenPolygon( contour );
// const Polygon* polygon = dynamic_cast<const Polygon*>( component );
// if (polygon) {
// vector< vector<Point> > subpolygons;
// polygon->getSubPolygons( subpolygons );
// for ( const vector<Point>& sp : subpolygons ) {
// contour.clear();
// for ( Point point : sp ) contour << _cellWidget->dbuToScreenPoint( point );
// _cellWidget->drawScreenPolygon( contour );
// }
// }
}
}
return;

View File

@ -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

View File

@ -66,8 +66,10 @@ def Place ( ins, sym, ref, plac = FIXED, cell = None ) :
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"

View File

@ -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 )