Add vertical rectangles partionning to Rectilinear.
* New: Rectilinear::asRectangles(), decompose the Rectilinear into a set of non-overlapping rectangles sliced vertically. This not a mathematical minimum set. But should be speedier. Done using a sweepline processing the vertical edges. Specially suited for use in the extractor which basically manage only rectangles. Simple algorithm described in pp. 9-11 of Extractor notebook. Tests done with unitests/python/test_rectilinear.py, the Rectilinear here should cover all the sweepline cases.
This commit is contained in:
parent
4c7cf227be
commit
52fd1c1c40
|
@ -40,6 +40,284 @@
|
|||
#include "hurricane/Warning.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace std;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Point;
|
||||
using Hurricane::Box;
|
||||
using Hurricane::Interval;
|
||||
using Hurricane::Rectilinear;
|
||||
|
||||
|
||||
class SweepInterval : public Interval {
|
||||
public:
|
||||
inline SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin );
|
||||
inline SweepInterval ( Interval&, DbU::Unit xmin );
|
||||
inline SweepInterval& inflate ( DbU::Unit dvMin, DbU::Unit dvMax );
|
||||
inline SweepInterval& merge ( DbU::Unit v );
|
||||
inline DbU::Unit getXMin () const;
|
||||
inline void setXMin ( DbU::Unit );
|
||||
inline string _getString () const;
|
||||
private:
|
||||
DbU::Unit _xMin;
|
||||
};
|
||||
|
||||
|
||||
inline SweepInterval::SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin )
|
||||
: Interval(vmin,vmax)
|
||||
, _xMin (xmin)
|
||||
{ }
|
||||
|
||||
inline SweepInterval::SweepInterval ( Interval& base, DbU::Unit xmin )
|
||||
: Interval(base)
|
||||
, _xMin (xmin)
|
||||
{ }
|
||||
|
||||
inline SweepInterval& SweepInterval::inflate ( DbU::Unit dvMin, DbU::Unit dvMax ) { Interval::inflate(dvMin,dvMax); return *this; }
|
||||
inline SweepInterval& SweepInterval::merge ( DbU::Unit v ) { Interval::merge(v); return *this; }
|
||||
inline DbU::Unit SweepInterval::getXMin () const { return _xMin; }
|
||||
inline void SweepInterval::setXMin ( DbU::Unit xmin ) { _xMin=xmin; }
|
||||
|
||||
inline string SweepInterval::_getString () const
|
||||
{
|
||||
string s;
|
||||
s += "@" + DbU::getValueString(_xMin);
|
||||
s += " [" + DbU::getValueString(getVMin());
|
||||
s += " " + DbU::getValueString(getVMax()) + "]";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
GETSTRING_VALUE_SUPPORT(::SweepInterval);
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class SweepLine {
|
||||
public:
|
||||
SweepLine ( const Rectilinear*, vector<Box>& );
|
||||
~SweepLine ();
|
||||
void addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x );
|
||||
void loadVEdges ();
|
||||
void process ( Interval );
|
||||
void process ( const pair< DbU::Unit, list<Interval> >& );
|
||||
void toBox ( SweepInterval& );
|
||||
void asRectangles ();
|
||||
private:
|
||||
const Rectilinear* _rectilinear;
|
||||
vector<Box>& _boxes;
|
||||
list< pair< DbU::Unit, list<Interval> > > _vedges;
|
||||
list< SweepInterval > _sweepLine;
|
||||
DbU::Unit _prevX;
|
||||
DbU::Unit _currX;
|
||||
};
|
||||
|
||||
|
||||
SweepLine::SweepLine ( const Rectilinear* r, vector<Box>& boxes )
|
||||
: _rectilinear(r)
|
||||
, _boxes (boxes)
|
||||
, _vedges ()
|
||||
, _sweepLine ()
|
||||
, _prevX (0)
|
||||
, _currX (0)
|
||||
{
|
||||
cdebug_log(17,1) << "SweepLine::SweepLine()" << endl;
|
||||
}
|
||||
|
||||
|
||||
SweepLine::~SweepLine ()
|
||||
{
|
||||
cdebug_tabw(17,-1);
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x )
|
||||
{
|
||||
if (ymin > ymax) std::swap( ymin, ymax );
|
||||
|
||||
cdebug_log(17,1) << "SweepLine::addVEdge() @"<< DbU::getValueString(x)
|
||||
<< " [" << DbU::getValueString(ymin)
|
||||
<< " " << DbU::getValueString(ymax) << "]" << endl;
|
||||
|
||||
bool inserted = false;
|
||||
for ( auto ix = _vedges.begin() ; ix != _vedges.end() ; ++ix ) {
|
||||
cdebug_log(17,0) << "| Looking @" << DbU::getValueString(ix->first)
|
||||
<< " size=" << ix->second.size() << endl;
|
||||
|
||||
if (ix->first > x) {
|
||||
_vedges.insert( ix, make_pair( x, list<Interval>() ));
|
||||
cdebug_log(17,0) << "+ add new @" << DbU::getValueString(x) << endl;
|
||||
--ix;
|
||||
}
|
||||
if (ix->first == x) {
|
||||
for ( auto iintv = ix->second.begin() ; iintv != ix->second.end() ; ++iintv ) {
|
||||
if (iintv->getVMin() >= ymax) {
|
||||
ix->second.insert( iintv, Interval(ymin,ymax) );
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not inserted) {
|
||||
ix->second.push_back( Interval(ymin,ymax) );
|
||||
inserted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not inserted) {
|
||||
cdebug_log(17,0) << "+ add new (back) @" << DbU::getValueString(x) << endl;
|
||||
_vedges.push_back( make_pair( x, list<Interval>() ));
|
||||
_vedges.back().second.push_back( Interval(ymin,ymax) );
|
||||
}
|
||||
|
||||
cdebug_tabw(17,-1);
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::loadVEdges ()
|
||||
{
|
||||
const vector<Point>& points = _rectilinear->getPoints();
|
||||
for ( size_t i=0 ; i<points.size() ; ++i ) {
|
||||
const Point& source = points[ i ];
|
||||
const Point& target = points[ (i+1) % points.size() ];
|
||||
DbU::Unit dx = target.getX() - source.getX();
|
||||
//DbU::Unit dy = target.getY() - source.getY();
|
||||
if (dx == 0) {
|
||||
addVEdge( source.getY(), target.getY(), source.getX() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::toBox ( SweepInterval& intv )
|
||||
{
|
||||
if (intv.getXMin() == _currX) return;
|
||||
_boxes.push_back( Box( intv.getXMin(), intv.getVMin()
|
||||
, _currX , intv.getVMax() ));
|
||||
intv.setXMin( _currX );
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::process ( Interval v )
|
||||
{
|
||||
cdebug_log(17,1) << "SweepLine::process(Interval&) "
|
||||
<< " [" << DbU::getValueString(v.getVMin())
|
||||
<< " " << DbU::getValueString(v.getVMax()) << "]" << endl;
|
||||
bool done = false;
|
||||
for ( auto iintv = _sweepLine.begin() ; iintv != _sweepLine.end() ; ++iintv ) {
|
||||
// Extractor p. 9 (a).
|
||||
if (v.getVMax() < iintv->getVMin()) {
|
||||
_sweepLine.insert( iintv, SweepInterval(v,_currX) );
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (f).
|
||||
if ( (v.getVMin() == iintv->getVMin())
|
||||
and (v.getVMax() == iintv->getVMax()) ) {
|
||||
toBox( *iintv );
|
||||
_sweepLine.erase( iintv );
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (b).
|
||||
if (v.getVMax() == iintv->getVMin()) {
|
||||
toBox( *iintv );
|
||||
iintv->merge( v.getVMin() );
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (g).
|
||||
if (v.getVMax() == iintv->getVMax()) {
|
||||
toBox( *iintv );
|
||||
cdebug_log(17,0) << "case (g): carve" << endl;
|
||||
iintv->inflate( 0, v.getVMin() - iintv->getVMax() );
|
||||
cdebug_log(17,0) << "| " << (*iintv) << endl;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (h).
|
||||
if (v.getVMin() == iintv->getVMin()) {
|
||||
toBox( *iintv );
|
||||
iintv->inflate(iintv->getVMin() - v.getVMax(), 0 );
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (c).
|
||||
if ( (v.getVMin() > iintv->getVMin())
|
||||
and (v.getVMax() < iintv->getVMax()) ) {
|
||||
toBox( *iintv );
|
||||
cdebug_log(17,0) << "case (c): carve" << endl;
|
||||
DbU::Unit wholeVMin = iintv->getVMin();
|
||||
iintv->inflate( iintv->getVMin() - v.getVMax(), 0 );
|
||||
cdebug_log(17,0) << "| " << (*iintv) << endl;
|
||||
_sweepLine.insert( iintv, SweepInterval( wholeVMin, v.getVMin(), _currX ) );
|
||||
cdebug_log(17,0) << "| " << (*(--iintv)) << endl;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
// Extractor p. 9 (d,e).
|
||||
if (v.getVMin() == iintv->getVMax()) {
|
||||
auto iintvNext = iintv;
|
||||
++iintvNext;
|
||||
// Extractor p. 9 (d).
|
||||
if (iintvNext == _sweepLine.end()) {
|
||||
toBox( *iintv );
|
||||
iintv->merge( v.getVMax() );
|
||||
} else {
|
||||
// Extractor p. 9 (d).
|
||||
if (v.getVMax() < iintvNext->getVMin()) {
|
||||
toBox( *iintv );
|
||||
iintv->merge( v.getVMax() );
|
||||
} else {
|
||||
// Extractor p. 9 (e).
|
||||
toBox( *iintv );
|
||||
toBox( *iintvNext );
|
||||
iintv->merge( iintvNext->getVMax() );
|
||||
_sweepLine.erase( iintvNext );
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not done) {
|
||||
_sweepLine.push_back( SweepInterval(v,_currX) );
|
||||
}
|
||||
|
||||
cdebug_tabw(17,-1);
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::process ( const pair< DbU::Unit, list<Interval> >& intervals )
|
||||
{
|
||||
cdebug_log(17,1) << "SweepLine::process() @"<< DbU::getValueString(intervals.first)
|
||||
<< " size=" << intervals.second.size() << endl;
|
||||
_currX = intervals.first;
|
||||
for ( const Interval& v : intervals.second ) process( v );
|
||||
cdebug_tabw(17,-1);
|
||||
}
|
||||
|
||||
|
||||
void SweepLine::asRectangles ()
|
||||
{
|
||||
loadVEdges();
|
||||
for ( auto intervals : _vedges ) {
|
||||
process( intervals );
|
||||
}
|
||||
cdebug_log(17,0) << "SweepLine::asRectangles() size=" << _boxes.size() << endl;
|
||||
for ( const Box& b : _boxes )
|
||||
cdebug_log(17,0) << "| " << b << endl;
|
||||
}
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace Hurricane {
|
||||
|
||||
|
||||
|
@ -50,6 +328,7 @@ namespace Hurricane {
|
|||
: Super (net)
|
||||
, _layer (layer)
|
||||
, _points(points)
|
||||
, _flags (IsRectilinear)
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -61,6 +340,7 @@ namespace Hurricane {
|
|||
if (points.size() > 1000)
|
||||
throw Error( "Rectilinear::create(): Rectlinear polygons must not exceed 1000 vertexes." );
|
||||
|
||||
bool isRect = true;
|
||||
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
|
||||
for ( size_t i=0 ; i<points.size() ; ++i ) {
|
||||
size_t j = (i+1) % points.size();
|
||||
|
@ -68,9 +348,12 @@ namespace Hurricane {
|
|||
DbU::Unit dx = std::abs( points[i].getX() - points[j].getX() );
|
||||
DbU::Unit dy = std::abs( points[i].getY() - points[j].getY() );
|
||||
|
||||
if ( (dx != 0) and (dy != 0) and (dx != dy) )
|
||||
throw Error( "Rectilinear::create(): Can't create, non H/V edge (points %d:%s - %d:%s)."
|
||||
, i, getString(points[i]).c_str(), j, getString(points[j]).c_str() );
|
||||
if ((dx != 0) and (dy != 0)) {
|
||||
isRect = false;
|
||||
if (dx != dy)
|
||||
throw Error( "Rectilinear::create(): Can't create, non H/V edge (points %d:%s - %d:%s)."
|
||||
, i, getString(points[i]).c_str(), j, getString(points[j]).c_str() );
|
||||
}
|
||||
|
||||
if (points[i].getX() % oneGrid)
|
||||
cerr << Warning( "Rectilinear::create(): In Cell \"%s\", Net \"%s\",\n"
|
||||
|
@ -91,7 +374,7 @@ namespace Hurricane {
|
|||
}
|
||||
|
||||
Rectilinear* rectilinear = new Rectilinear ( net, layer, points );
|
||||
|
||||
if (not isRect) rectilinear->_flags &= ~IsRectilinear;
|
||||
rectilinear->_postCreate();
|
||||
|
||||
return rectilinear;
|
||||
|
@ -176,6 +459,15 @@ namespace Hurricane {
|
|||
}
|
||||
|
||||
|
||||
bool Rectilinear::getAsRectangles ( std::vector<Box>& rectangles ) const
|
||||
{
|
||||
rectangles.clear();
|
||||
if (not isRectilinear()) return false;
|
||||
SweepLine( this, rectangles ).asRectangles();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Rectilinear::_toJson ( JsonWriter* writer ) const
|
||||
{
|
||||
Inherit::_toJson( writer );
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved
|
||||
// Copyright (c) BULL S.A. 2018-2023, All Rights Reserved
|
||||
//
|
||||
// This file is part of Hurricane.
|
||||
//
|
||||
|
@ -28,10 +28,7 @@
|
|||
// | C++ Header : "./hurricane/Rectilinear.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef HURRICANE_RECTILINEAR_H
|
||||
#define HURRICANE_RECTILINEAR_H
|
||||
|
||||
#pragma once
|
||||
#include "hurricane/Component.h"
|
||||
|
||||
|
||||
|
@ -46,11 +43,13 @@ namespace Hurricane {
|
|||
class Rectilinear : public Component {
|
||||
public:
|
||||
typedef Component Super;
|
||||
static const uint32_t IsRectilinear = (1<<0);
|
||||
|
||||
public:
|
||||
static Rectilinear* create ( Net*, const Layer*, const vector<Point>& );
|
||||
// Accessors.
|
||||
virtual bool isNonRectangle () const;
|
||||
inline bool isRectilinear () const;
|
||||
virtual DbU::Unit getX () const;
|
||||
virtual DbU::Unit getY () const;
|
||||
virtual Box getBoundingBox () const;
|
||||
|
@ -59,6 +58,7 @@ namespace Hurricane {
|
|||
virtual Point getPoint ( size_t i ) const;
|
||||
virtual const Layer* getLayer () const;
|
||||
inline Points getContour () const;
|
||||
bool getAsRectangles ( std::vector<Box>& ) const;
|
||||
inline const vector<Point>& getPoints () const;
|
||||
// Mutators.
|
||||
void setLayer ( const Layer* );
|
||||
|
@ -75,11 +75,13 @@ namespace Hurricane {
|
|||
private:
|
||||
const Layer* _layer;
|
||||
vector<Point> _points;
|
||||
uint32_t _flags;
|
||||
};
|
||||
|
||||
|
||||
inline Points Rectilinear::getContour () const { return new VectorCollection<Point>(_points); }
|
||||
inline const vector<Point>& Rectilinear::getPoints () const { return _points; }
|
||||
inline bool Rectilinear::isRectilinear () const { return _flags & IsRectilinear; }
|
||||
inline Points Rectilinear::getContour () const { return new VectorCollection<Point>(_points); }
|
||||
inline const vector<Point>& Rectilinear::getPoints () const { return _points; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -99,5 +101,3 @@ namespace Hurricane {
|
|||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Hurricane::Rectilinear);
|
||||
|
||||
#endif // HURRICANE_RECTILINEAR_H
|
||||
|
|
|
@ -45,6 +45,24 @@ namespace Isobar {
|
|||
}
|
||||
|
||||
|
||||
PyObject* VectorToList ( const std::vector<Box>& v )
|
||||
{
|
||||
PyObject* pyList = PyList_New( v.size() );
|
||||
|
||||
for ( size_t i=0 ; i<v.size() ; ++i ) {
|
||||
PyBox* pyBox = PyObject_NEW( PyBox, &PyTypeBox );
|
||||
if (not pyBox) { return NULL; }
|
||||
|
||||
HTRY
|
||||
pyBox->_object = new Box ( v[i] );
|
||||
HCATCH
|
||||
PyList_SetItem( pyList, i, (PyObject*)pyBox );
|
||||
}
|
||||
|
||||
return pyList;
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
|
@ -168,20 +186,54 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
static PyObject* PyRectilinear_getAsRectangles ( PyRectilinear *self, PyObject* args )
|
||||
{
|
||||
cdebug_log(20,0) << "Rectilinear.getAsRectangles()" << endl;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD( "Rectilinear.getAsRectangles()" )
|
||||
|
||||
PyObject* pyList = NULL;
|
||||
if (not PyArg_ParseTuple( args, "O:Rectilinear.getAsRectangles", &pyList )) {
|
||||
PyErr_SetString( ConstructorError, "Rectilinear.getAsRectangles(): Must have exactly one parameter." );
|
||||
return NULL;
|
||||
}
|
||||
if (not PyList_Check(pyList)) {
|
||||
PyErr_SetString( ConstructorError, "Rectilinear.getAsRectangles(): Argument must be a list." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyList_SetSlice( pyList, 0, PyList_Size(pyList), NULL );
|
||||
vector<Box> boxes;
|
||||
rectilinear->getAsRectangles( boxes );
|
||||
for ( size_t i=0 ; i<boxes.size() ; ++i ) {
|
||||
PyBox* pyBox = PyObject_NEW( PyBox, &PyTypeBox );
|
||||
if (not pyBox) { return NULL; }
|
||||
|
||||
pyBox->_object = new Box ( boxes[i] );
|
||||
PyList_Append( pyList, (PyObject*)pyBox );
|
||||
}
|
||||
HCATCH
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// PyRectilinear Attribute Method table.
|
||||
|
||||
PyMethodDef PyRectilinear_Methods[] =
|
||||
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
|
||||
, "Create a new Rectilinear polygon." }
|
||||
, { "isNonRectangle", (PyCFunction)PyRectilinear_isNonRectangle, METH_NOARGS , "Tells if the shape is not a rectangle." }
|
||||
, { "getX" , (PyCFunction)PyRectilinear_getX , METH_NOARGS , "Return the Rectilinear X value." }
|
||||
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
|
||||
, { "getBoundingBox", (PyCFunction)PyRectilinear_getBoundingBox, METH_NOARGS , "Return the Rectilinear Bounding Box." }
|
||||
, { "setPoints" , (PyCFunction)PyRectilinear_setPoints , METH_VARARGS, "Sets the Rectilinear Bounding Box." }
|
||||
, { "translate" , (PyCFunction)PyRectilinear_translate , METH_VARARGS, "Translates the Rectilinear of dx and dy." }
|
||||
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
|
||||
, "Destroy associated hurricane object, the python object remains." }
|
||||
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
|
||||
, "Create a new Rectilinear polygon." }
|
||||
, { "isNonRectangle" , (PyCFunction)PyRectilinear_isNonRectangle , METH_NOARGS , "Tells if the shape is not a rectangle." }
|
||||
, { "getX" , (PyCFunction)PyRectilinear_getX , METH_NOARGS , "Return the Rectilinear X value." }
|
||||
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
|
||||
, { "getBoundingBox" , (PyCFunction)PyRectilinear_getBoundingBox , METH_NOARGS , "Return the Rectilinear Bounding Box." }
|
||||
, { "setPoints" , (PyCFunction)PyRectilinear_setPoints , METH_VARARGS, "Sets the Rectilinear Bounding Box." }
|
||||
, { "translate" , (PyCFunction)PyRectilinear_translate , METH_VARARGS, "Translates the Rectilinear of dx and dy." }
|
||||
, { "getAsRectangles", (PyCFunction)PyRectilinear_getAsRectangles, METH_VARARGS, "Return the rectangle coverage." }
|
||||
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
|
||||
, "Destroy associated hurricane object, the python object remains." }
|
||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import sys
|
||||
from coriolis.Hurricane import DataBase, Net, \
|
||||
DbU, Point, Box, Pad, Rectilinear
|
||||
from coriolis import Cfg
|
||||
from coriolis.CRL import AllianceFramework, Catalog, Gds
|
||||
from coriolis.helpers import l, u
|
||||
from coriolis.helpers.overlay import CfgCache, UpdateSession
|
||||
|
||||
|
||||
def testRectilinear ( editor ):
|
||||
"""Check Hurricane.Rectilinear class."""
|
||||
with CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
|
||||
cfg.misc.minTraceLevel = 17000
|
||||
cfg.misc.maxTraceLevel = 18000
|
||||
with UpdateSession():
|
||||
cell = AllianceFramework.get().createCell( 'Rectilinear' )
|
||||
cell.setTerminalNetlist( True )
|
||||
cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(400.0), l(200.0) ) )
|
||||
#cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(21.0), l(35.0) ) )
|
||||
if editor:
|
||||
editor.setCell( cell )
|
||||
editor.fit()
|
||||
|
||||
technology = DataBase.getDB().getTechnology()
|
||||
metal1 = technology.getLayer( "METAL1" )
|
||||
metal2 = technology.getLayer( "METAL2" )
|
||||
metal3 = technology.getLayer( "METAL3" )
|
||||
metal4 = technology.getLayer( "METAL4" )
|
||||
poly = technology.getLayer( "POLY" )
|
||||
ptrans = technology.getLayer( "PTRANS" )
|
||||
ntrans = technology.getLayer( "NTRANS" )
|
||||
pdif = technology.getLayer( "PDIF" )
|
||||
ndif = technology.getLayer( "NDIF" )
|
||||
contdifn = technology.getLayer( "CONT_DIF_N" )
|
||||
contdifp = technology.getLayer( "CONT_DIF_P" )
|
||||
nwell = technology.getLayer( "NWELL" )
|
||||
contpoly = technology.getLayer( "CONT_POLY" )
|
||||
ntie = technology.getLayer( "NTIE" )
|
||||
|
||||
with UpdateSession():
|
||||
net = Net.create( cell, 'my_net' )
|
||||
net.setExternal( True )
|
||||
|
||||
points = [ Point( l( 0.0), l( 0.0) )
|
||||
, Point( l( 0.0), l( 10.0) )
|
||||
, 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) ) ]
|
||||
r = Rectilinear.create( net, metal2, points )
|
||||
|
||||
#print( 'Normalized and manhattanized contour:' )
|
||||
#i = 0
|
||||
#for point in p.getMContour():
|
||||
# print( '| %d '%i, point, '[%fum %fum]' % ( u(point.getX()), u(point.getY()) ))
|
||||
# i += 1
|
||||
|
||||
#points = [ Point( l( 0.0), l( 40.0) ) # 0
|
||||
# , Point( l( 30.0), l( 40.0) ) # 1
|
||||
# , Point( l( 30.0), l( 60.0) ) # 2
|
||||
# , Point( l( 50.0), l( 60.0) ) # 3
|
||||
# , Point( l( 50.0), l( 80.0) ) # 4
|
||||
# , Point( l( 90.0), l( 80.0) ) # 5
|
||||
# , Point( l( 90.0), l( 50.0) ) # 6
|
||||
# , Point( l( 60.0), l( 50.0) ) # 7
|
||||
# , Point( l( 60.0), l( 30.0) ) # 8
|
||||
# , Point( l( 70.0), l( 30.0) ) # 9
|
||||
# , Point( l( 70.0), l( 20.0) ) # 10
|
||||
# , Point( l( 90.0), l( 20.0) ) # 11
|
||||
# , 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
|
||||
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
|
||||
, Point( l( 10.0), l( 30.0) ) # 3
|
||||
, Point( l( 20.0), l( 30.0) ) # 4
|
||||
, Point( l( 20.0), l( 40.0) ) # 5
|
||||
, Point( l( 40.0), l( 40.0) ) # 6
|
||||
, 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
|
||||
, Point( l( 0.0), l(120.0) ) # 13
|
||||
, Point( l( 10.0), l(120.0) ) # 14
|
||||
, Point( l( 10.0), l(110.0) ) # 15
|
||||
, Point( l( 20.0), l(110.0) ) # 16
|
||||
, 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
|
||||
, Point( l( 10.0), l(160.0) ) # 23
|
||||
, Point( l( 0.0), l(160.0) ) # 24
|
||||
, Point( l( 0.0), l(180.0) ) # 25
|
||||
, Point( l( 40.0), l(180.0) ) # 26
|
||||
, 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
|
||||
, Point( l(130.0), l(140.0) ) # 33
|
||||
, Point( l(120.0), l(140.0) ) # 34
|
||||
, Point( l(120.0), l(130.0) ) # 35
|
||||
, Point( l(110.0), l(130.0) ) # 36
|
||||
, 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
|
||||
, Point( l(150.0), l( 80.0) ) # 43
|
||||
, Point( l(120.0), l( 80.0) ) # 44
|
||||
, Point( l(120.0), l( 70.0) ) # 45
|
||||
, Point( l(110.0), l( 70.0) ) # 46
|
||||
, 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
|
||||
, Point( l(150.0), l( 20.0) ) # 53
|
||||
, 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
|
||||
r = Rectilinear.create( net, metal2, points )
|
||||
|
||||
boxes = []
|
||||
r.getAsRectangles( boxes )
|
||||
#print( 'boxes={}'.format( boxes ))
|
||||
for box in boxes:
|
||||
box.translate( l(180.0), l(0.0) )
|
||||
Pad.create( net, metal3, box )
|
||||
|
||||
Gds.save( cell )
|
||||
|
||||
|
||||
def scriptMain ( **kw ):
|
||||
"""The mandatory function to be called by Coriolis CGT/Unicorn."""
|
||||
editor = None
|
||||
if 'editor' in kw and kw['editor']:
|
||||
editor = kw['editor']
|
||||
testRectilinear( editor )
|
||||
return True
|
Loading…
Reference in New Issue