Merge branch 'master' into robtaylor/room-link
This commit is contained in:
commit
c9cbf87c10
|
@ -11,6 +11,7 @@ This project is hosted at: https://github.com/lip6/coriolis
|
||||||
|
|
||||||
Development discussion can be found at https://matrix.to/#/#coriolis:matrix.org
|
Development discussion can be found at https://matrix.to/#/#coriolis:matrix.org
|
||||||
|
|
||||||
|
|
||||||
Purpose
|
Purpose
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
|
|
@ -1782,6 +1782,18 @@ namespace {
|
||||||
NetExternalComponents::setExternal( p );
|
NetExternalComponents::setExternal( p );
|
||||||
toDestroy.push_back( component );
|
toDestroy.push_back( component );
|
||||||
cdebug_log(101,0) << "> external duplicate " << p << endl;
|
cdebug_log(101,0) << "> external duplicate " << p << endl;
|
||||||
|
} else {
|
||||||
|
Rectilinear* rectilinear = dynamic_cast<Rectilinear*>( component );
|
||||||
|
if (rectilinear) {
|
||||||
|
rectilinear = Rectilinear::create( net
|
||||||
|
, rectilinear->getLayer()
|
||||||
|
, rectilinear->getPoints() );
|
||||||
|
NetExternalComponents::setExternal( rectilinear );
|
||||||
|
} else {
|
||||||
|
cerr << Error( "GdsStream::makeExternals(): Unmanaged component %s for net \"%s\"."
|
||||||
|
, getString(component).c_str()
|
||||||
|
, getString(net->getName()).c_str() ) << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -615,8 +615,6 @@ namespace {
|
||||||
Net* net = Net::create( parser->getCell(), pin->name() );
|
Net* net = Net::create( parser->getCell(), pin->name() );
|
||||||
net->setExternal( true );
|
net->setExternal( true );
|
||||||
|
|
||||||
if (pin->name()[ strlen(pin->name())-1 ] == '!') net->setGlobal( true );
|
|
||||||
|
|
||||||
if (pin->hasDirection()) {
|
if (pin->hasDirection()) {
|
||||||
string lefDir = pin->direction();
|
string lefDir = pin->direction();
|
||||||
boost::to_upper( lefDir );
|
boost::to_upper( lefDir );
|
||||||
|
@ -637,6 +635,8 @@ namespace {
|
||||||
if (lefUse == "POWER" ) net->setType( Net::Type::POWER );
|
if (lefUse == "POWER" ) net->setType( Net::Type::POWER );
|
||||||
if (lefUse == "GROUND") net->setType( Net::Type::GROUND );
|
if (lefUse == "GROUND") net->setType( Net::Type::GROUND );
|
||||||
}
|
}
|
||||||
|
if (net->isSupply()) net->setGlobal( true );
|
||||||
|
if (pin->name()[ strlen(pin->name())-1 ] == '!') net->setGlobal( true );
|
||||||
|
|
||||||
for ( int iport=0 ; iport < pin->numPorts() ; ++iport ) {
|
for ( int iport=0 ; iport < pin->numPorts() ; ++iport ) {
|
||||||
Layer* layer = NULL;
|
Layer* layer = NULL;
|
||||||
|
@ -727,27 +727,30 @@ namespace {
|
||||||
const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 );
|
const RoutingLayerGauge* gaugeMetal2 = _routingGauge->getLayerGauge( 1 );
|
||||||
Box ab = _cell->getAbutmentBox();
|
Box ab = _cell->getAbutmentBox();
|
||||||
|
|
||||||
cerr << " @ _pinStdPostProcess" << endl;
|
//cerr << " @ _pinStdPostProcess" << endl;
|
||||||
|
|
||||||
for ( auto element : _pinComponents ) {
|
for ( auto element : _pinComponents ) {
|
||||||
string pinName = element.first;
|
string pinName = element.first;
|
||||||
vector<Component*>& components = element.second;
|
vector<Component*>& components = element.second;
|
||||||
vector<Segment*> ongrids;
|
vector<Segment*> ongrids;
|
||||||
|
bool isSupply = false;
|
||||||
|
|
||||||
for ( Component* component : components ) {
|
for ( Component* component : components ) {
|
||||||
|
if (component->getNet()->isSupply()) {
|
||||||
|
isSupply = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Segment* segment = dynamic_cast<Segment*>( component );
|
Segment* segment = dynamic_cast<Segment*>( component );
|
||||||
if (segment) {
|
if (segment) {
|
||||||
if (component->getNet()->isSupply()) continue;
|
|
||||||
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
|
bool isWide = (segment->getWidth() >= getMinTerminalWidth());
|
||||||
|
|
||||||
cerr << " > " << segment << endl;
|
// cerr << " > " << segment << endl;
|
||||||
if (not isVH())
|
// if (not isVH()) cerr << "X NOT isVH()" << endl;
|
||||||
cerr << "NOT isVH()" << endl;
|
// else cerr << "X isVH()" << endl;
|
||||||
else
|
|
||||||
cerr << "isVH()" << endl;
|
|
||||||
|
|
||||||
if (isVH() and (segment->getLayer()->getMask() == metal1->getMask())) {
|
if (isVH() and (segment->getLayer()->getMask() == metal1->getMask())) {
|
||||||
cerr << "isVH()" << endl;
|
// cerr << "isVH()" << endl;
|
||||||
Vertical* v = dynamic_cast<Vertical*>( segment );
|
Vertical* v = dynamic_cast<Vertical*>( segment );
|
||||||
if (v) {
|
if (v) {
|
||||||
DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin()
|
DbU::Unit nearestX = gaugeMetal2->getTrackPosition( ab.getXMin()
|
||||||
|
@ -775,7 +778,7 @@ namespace {
|
||||||
, v->getDyTarget()
|
, v->getDyTarget()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
//cerr << " | " << ongrids[ongrids.size()-1] << endl;
|
cerr << " | " << ongrids[ongrids.size()-1] << endl;
|
||||||
} else {
|
} else {
|
||||||
// Unpitched and not wide enough to be under a metal2 track, ignore.
|
// Unpitched and not wide enough to be under a metal2 track, ignore.
|
||||||
}
|
}
|
||||||
|
@ -788,11 +791,11 @@ namespace {
|
||||||
if (isWide) ongrids.push_back( segment );
|
if (isWide) ongrids.push_back( segment );
|
||||||
}
|
}
|
||||||
Rectilinear* rectilinear = dynamic_cast<Rectilinear*>( component );
|
Rectilinear* rectilinear = dynamic_cast<Rectilinear*>( component );
|
||||||
if (not (rectilinear->getLayer()->getMask() == metal1->getMask()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rectilinear) {
|
if (rectilinear) {
|
||||||
cerr << " > " << rectilinear << endl;
|
cerr << " > " << rectilinear << endl;
|
||||||
|
if (rectilinear->getLayer()->getMask() != metal1->getMask())
|
||||||
|
continue;
|
||||||
|
|
||||||
vector<Box> boxes;
|
vector<Box> boxes;
|
||||||
rectilinear->getAsRectangles( boxes );
|
rectilinear->getAsRectangles( boxes );
|
||||||
|
|
||||||
|
@ -841,8 +844,9 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ongrids.empty()) {
|
if (ongrids.empty()) {
|
||||||
cerr << Warning( "LefParser::_pinStdPostProcess(): Pin \"%s\" has no terminal ongrid."
|
if (not isSupply)
|
||||||
, pinName.c_str() ) << endl;
|
cerr << Warning( "LefParser::_pinStdPostProcess(): Pin \"%s\" has no terminal ongrid."
|
||||||
|
, pinName.c_str() ) << endl;
|
||||||
for ( Component* component : components ) {
|
for ( Component* component : components ) {
|
||||||
NetExternalComponents::setExternal( component );
|
NetExternalComponents::setExternal( component );
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +1012,7 @@ namespace {
|
||||||
if (parser->getCoreSiteY() != parser->getCellGauge()->getSliceHeight())
|
if (parser->getCoreSiteY() != parser->getCellGauge()->getSliceHeight())
|
||||||
cerr << Warning( "LefParser::parse(): CRL slice height discrepency %s while LEF is %s."
|
cerr << Warning( "LefParser::parse(): CRL slice height discrepency %s while LEF is %s."
|
||||||
, DbU::getValueString(parser->getCellGauge()->getSliceHeight()).c_str()
|
, DbU::getValueString(parser->getCellGauge()->getSliceHeight()).c_str()
|
||||||
, DbU::getValueString(parser->getCoreSiteX()).c_str() ) << endl;
|
, DbU::getValueString(parser->getCoreSiteY()).c_str() ) << endl;
|
||||||
|
|
||||||
if (parser->getCoreSiteX() != parser->getCellGauge()->getSliceStep())
|
if (parser->getCoreSiteX() != parser->getCellGauge()->getSliceStep())
|
||||||
cerr << Warning( "LefParser::parse(): CRL slice step discrepency %s while LEF is %s."
|
cerr << Warning( "LefParser::parse(): CRL slice step discrepency %s while LEF is %s."
|
||||||
|
|
|
@ -744,7 +744,10 @@ class IoPadConf ( object ):
|
||||||
else:
|
else:
|
||||||
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
|
if self._datas[5] is not None: self.flags |= IoPadConf.BIDIR
|
||||||
elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE
|
elif self._datas[6] is not None: self.flags |= IoPadConf.TRISTATE
|
||||||
trace( 550, '\tIoPadConf._datas: {}\n'.format(self._datas) )
|
sPos = ''
|
||||||
|
if self._datas[1]:
|
||||||
|
sPos = DbU.getValueString(self._datas[1])
|
||||||
|
trace( 550, '\tIoPadConf._datas: @{} {}\n'.format(sPos,self._datas) )
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def side ( self ): return self._datas[0]
|
def side ( self ): return self._datas[0]
|
||||||
|
|
|
@ -106,7 +106,11 @@ class HTree ( object ):
|
||||||
hLeafDepth = gaugeConf.horizontalDepth - 2
|
hLeafDepth = gaugeConf.horizontalDepth - 2
|
||||||
gaugeConf.setStackPosition( contact, x, y )
|
gaugeConf.setStackPosition( contact, x, y )
|
||||||
gaugeConf.createVertical ( contact, forkContact, x, 0 )
|
gaugeConf.createVertical ( contact, forkContact, x, 0 )
|
||||||
gaugeConf.addTrackAvoid( Box( x, forkContact.getY(), x, y ) )
|
trackAvoidBox = Box( x, forkContact.getY(), x, y )
|
||||||
|
if forkContact.getY() > contact.getY():
|
||||||
|
trackAvoidBox.inflate( 0, 0, 0, self.spares.conf.sliceHeight )
|
||||||
|
gaugeConf.addTrackAvoid( trackAvoidBox )
|
||||||
|
self.spares.trackAvoid( trackAvoidBox )
|
||||||
if len(leaf.buffers) > 1:
|
if len(leaf.buffers) > 1:
|
||||||
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input, ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input, ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
||||||
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input, ckNet )
|
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input, ckNet )
|
||||||
|
|
|
@ -1103,8 +1103,8 @@ class Spares ( object ):
|
||||||
trace( 540, ',+', '\tSpares.addStrayBuffer()\n' )
|
trace( 540, ',+', '\tSpares.addStrayBuffer()\n' )
|
||||||
|
|
||||||
sliceHeight = self.conf.sliceHeight
|
sliceHeight = self.conf.sliceHeight
|
||||||
x = self.quadTree.toXPitch( position.getX() )
|
x = self.toXPitch( position.getX() )
|
||||||
y = self.quadTree.toYSlice( position.getY() )
|
y = self.toYSlice( position.getY() )
|
||||||
slice = y // sliceHeight
|
slice = y // sliceHeight
|
||||||
orientation = Transformation.Orientation.ID
|
orientation = Transformation.Orientation.ID
|
||||||
y = slice * sliceHeight
|
y = slice * sliceHeight
|
||||||
|
@ -1134,6 +1134,37 @@ class Spares ( object ):
|
||||||
raise ErrorMessage( 2, 'Spares.getFreeBufferUnder(): No more free buffers under {}.'.format(area) )
|
raise ErrorMessage( 2, 'Spares.getFreeBufferUnder(): No more free buffers under {}.'.format(area) )
|
||||||
return leaf.selectFree()
|
return leaf.selectFree()
|
||||||
|
|
||||||
|
def trackAvoid ( self, box ):
|
||||||
|
"""
|
||||||
|
Protect a vertical track by putting a vertical column of narrow filler
|
||||||
|
under it (usually tie). Used by the H-Tree (clock tree) in low-metal
|
||||||
|
nodes.
|
||||||
|
"""
|
||||||
|
trace( 540, ',+', '\tSpares.trackAvoid() {}\n'.format( box ))
|
||||||
|
yoffset = 0
|
||||||
|
if self.conf.isCoreBlock:
|
||||||
|
yoffset = self.conf.icore.getTransformation().getTy()
|
||||||
|
sliceHeight = self.conf.sliceHeight
|
||||||
|
x = self.toXPitch( box.getXMin() ) - self.conf.sliceStep
|
||||||
|
ymin = self.toYSlice( box.getYMin() )
|
||||||
|
ymax = self.toYSlice( box.getYMax() )
|
||||||
|
sliceMin = (ymin - yoffset) // sliceHeight
|
||||||
|
sliceMax = (ymax - yoffset) // sliceHeight
|
||||||
|
orientation = Transformation.Orientation.ID
|
||||||
|
ymin = sliceMin * sliceHeight
|
||||||
|
for row in range( sliceMin+1, sliceMax ):
|
||||||
|
orientation = Transformation.Orientation.ID
|
||||||
|
y = row * sliceHeight + yoffset
|
||||||
|
if row%2:
|
||||||
|
orientation = Transformation.Orientation.MY
|
||||||
|
y += sliceHeight
|
||||||
|
transf = Transformation( x, y, orientation )
|
||||||
|
instance = self.conf.feedsConf.createFeed( self.conf.corona )
|
||||||
|
instance.setTransformation( transf )
|
||||||
|
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
||||||
|
trace( 540, '\ttrackAvoid, feed: {} @{}\n'.format(instance,transf) )
|
||||||
|
trace( 540, '-' )
|
||||||
|
|
||||||
def raddTransNet ( self, topNet, path ):
|
def raddTransNet ( self, topNet, path ):
|
||||||
"""
|
"""
|
||||||
Add a net through a whole hierarchy of Instance/Cells. The master cells
|
Add a net through a whole hierarchy of Instance/Cells. The master cells
|
||||||
|
|
|
@ -169,7 +169,7 @@ class Side ( object ):
|
||||||
self.type = sideType
|
self.type = sideType
|
||||||
self.corona = corona
|
self.corona = corona
|
||||||
self.pins = []
|
self.pins = []
|
||||||
self.u = self.conf.ioPadHeight
|
self.u = 0
|
||||||
self.spacerCount = 0
|
self.spacerCount = 0
|
||||||
self.gap = 0
|
self.gap = 0
|
||||||
self.coreWires = []
|
self.coreWires = []
|
||||||
|
@ -370,6 +370,10 @@ class Side ( object ):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _placePads ( self ):
|
def _placePads ( self ):
|
||||||
|
if self.type in (North,South):
|
||||||
|
self.u = self.corona.padCornerWidth
|
||||||
|
else:
|
||||||
|
self.u = self.corona.padCornerHeight
|
||||||
padLength = 0
|
padLength = 0
|
||||||
for pad in self.pads: padLength += pad[1].getMasterCell().getAbutmentBox().getWidth()
|
for pad in self.pads: padLength += pad[1].getMasterCell().getAbutmentBox().getWidth()
|
||||||
padSpacing = (self.sideLength - 2*self.conf.ioPadHeight - padLength) // (len(self.pads) + 1)
|
padSpacing = (self.sideLength - 2*self.conf.ioPadHeight - padLength) // (len(self.pads) + 1)
|
||||||
|
@ -551,6 +555,8 @@ class Corona ( object ):
|
||||||
self.padCorner = []
|
self.padCorner = []
|
||||||
self.padRails = [] # [ , [net, layer, axis, width] ]
|
self.padRails = [] # [ , [net, layer, axis, width] ]
|
||||||
self.powerCount = 0
|
self.powerCount = 0
|
||||||
|
self.padCornerWidth = self.conf.ioPadHeight
|
||||||
|
self.padCornerHeight = self.conf.ioPadHeight
|
||||||
self.conf.cfg.chip.padCoreSide = None
|
self.conf.cfg.chip.padCoreSide = None
|
||||||
if self.conf.cfg.chip.padCoreSide.lower() == 'south':
|
if self.conf.cfg.chip.padCoreSide.lower() == 'south':
|
||||||
self.padOrient = Transformation.Orientation.MY
|
self.padOrient = Transformation.Orientation.MY
|
||||||
|
@ -567,7 +573,9 @@ class Corona ( object ):
|
||||||
raise ErrorMessage( 1, 'Corona.__init__(): Missing spacer cell "{}"'.format(spacerName) )
|
raise ErrorMessage( 1, 'Corona.__init__(): Missing spacer cell "{}"'.format(spacerName) )
|
||||||
self.padSpacers = sorted( self.padSpacers, key=_cmpPad, reverse=True )
|
self.padSpacers = sorted( self.padSpacers, key=_cmpPad, reverse=True )
|
||||||
if self.conf.cfg.chip.padCorner is not None:
|
if self.conf.cfg.chip.padCorner is not None:
|
||||||
self.padCorner = self.padLib.getCell( self.conf.cfg.chip.padCorner )
|
self.padCorner = self.padLib.getCell( self.conf.cfg.chip.padCorner )
|
||||||
|
self.padCornerWidth = self.padCorner.getAbutmentBox().getWidth()
|
||||||
|
self.padCornerHeight = self.padCorner.getAbutmentBox().getHeight()
|
||||||
if self.conf.cfg.chip.minPadSpacing is None:
|
if self.conf.cfg.chip.minPadSpacing is None:
|
||||||
self.conf.cfg.chip.minPadSpacing = 0
|
self.conf.cfg.chip.minPadSpacing = 0
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "hurricane/Plug.h"
|
#include "hurricane/Plug.h"
|
||||||
#include "hurricane/RoutingPad.h"
|
#include "hurricane/RoutingPad.h"
|
||||||
#include "hurricane/Vertical.h"
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/Horizontal.h"
|
||||||
#include "hurricane/NetExternalComponents.h"
|
#include "hurricane/NetExternalComponents.h"
|
||||||
#include "hurricane/Path.h"
|
#include "hurricane/Path.h"
|
||||||
#include "hurricane/Library.h"
|
#include "hurricane/Library.h"
|
||||||
|
@ -50,6 +51,7 @@ namespace Etesian {
|
||||||
using Hurricane::Plug;
|
using Hurricane::Plug;
|
||||||
using Hurricane::RoutingPad;
|
using Hurricane::RoutingPad;
|
||||||
using Hurricane::Vertical;
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::Horizontal;
|
||||||
using Hurricane::NetExternalComponents;
|
using Hurricane::NetExternalComponents;
|
||||||
using Hurricane::DebugSession;
|
using Hurricane::DebugSession;
|
||||||
using Hurricane::UpdateSession;
|
using Hurricane::UpdateSession;
|
||||||
|
@ -57,6 +59,8 @@ namespace Etesian {
|
||||||
using CRL::CatalogExtension;
|
using CRL::CatalogExtension;
|
||||||
using CRL::getTransformation;
|
using CRL::getTransformation;
|
||||||
using CRL::RoutingLayerGauge;
|
using CRL::RoutingLayerGauge;
|
||||||
|
using Constant::LayerGaugeType;
|
||||||
|
using Constant::Direction;
|
||||||
using Etesian::EtesianEngine;
|
using Etesian::EtesianEngine;
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,7 +150,7 @@ namespace Etesian {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list<Tile>::iterator imerge = _tiles.end();
|
//list<Tile>::iterator imerge = _tiles.end();
|
||||||
for ( auto itile = _tiles.begin() ; itile != _tiles.end() ; ++itile ) {
|
for ( auto itile = _tiles.begin() ; itile != _tiles.end() ; ++itile ) {
|
||||||
if ((*itile).getXMin() > flatAb.getXMin()) {
|
if ((*itile).getXMin() > flatAb.getXMin()) {
|
||||||
_tiles.insert( itile, Tile(flatAb.getXMin(), flatAb.getWidth(), occurrence) );
|
_tiles.insert( itile, Tile(flatAb.getXMin(), flatAb.getWidth(), occurrence) );
|
||||||
|
@ -630,12 +634,15 @@ namespace Etesian {
|
||||||
if (not component->getLayer()->isBlockage()) continue;
|
if (not component->getLayer()->isBlockage()) continue;
|
||||||
cdebug_log(121,0) << "Looking at " << component << endl;
|
cdebug_log(121,0) << "Looking at " << component << endl;
|
||||||
Vertical* v = dynamic_cast<Vertical*>( component );
|
Vertical* v = dynamic_cast<Vertical*>( component );
|
||||||
if (not v) continue;
|
if ( not dynamic_cast<Vertical* >(component)
|
||||||
|
and not dynamic_cast<Horizontal*>(component)) continue;
|
||||||
|
|
||||||
RoutingLayerGauge* rlg = rg->getLayerGauge( v->getLayer()->getRoutingLayer() );
|
RoutingLayerGauge* rlg = rg->getLayerGauge( component->getLayer()->getRoutingLayer() );
|
||||||
if (not rlg) continue;
|
if (not rlg) continue;
|
||||||
|
if (rlg->getType() != LayerGaugeType::Default) continue;
|
||||||
|
if (rlg->getDirection() != Direction::Vertical) continue;
|
||||||
|
|
||||||
Box bb = v->getBoundingBox();
|
Box bb = component->getBoundingBox();
|
||||||
bb.inflate( -rlg->getWireWidth()/2, 0 );
|
bb.inflate( -rlg->getWireWidth()/2, 0 );
|
||||||
Transformation transf = tile.getInstance()->getTransformation();
|
Transformation transf = tile.getInstance()->getTransformation();
|
||||||
tile.getOccurrence().getPath().getTransformation().applyOn( transf );
|
tile.getOccurrence().getPath().getTransformation().applyOn( transf );
|
||||||
|
|
|
@ -479,6 +479,19 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Box Rectilinear::getNearestHSide ( DbU::Unit y ) const
|
||||||
|
{
|
||||||
|
Box side;
|
||||||
|
for ( size_t i=1 ; i<_points.size() ; ++i ) {
|
||||||
|
if (_points[i-1].getY() != _points[i].getY()) continue;
|
||||||
|
if ( not side.isEmpty()
|
||||||
|
and (std::abs(side.getYCenter() - y) >= std::abs(_points[i].getY() - y))) continue;
|
||||||
|
side = Box( _points[i-1], _points[i] );
|
||||||
|
}
|
||||||
|
return side;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Rectilinear::_toJson ( JsonWriter* writer ) const
|
void Rectilinear::_toJson ( JsonWriter* writer ) const
|
||||||
{
|
{
|
||||||
Inherit::_toJson( writer );
|
Inherit::_toJson( writer );
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace Hurricane {
|
||||||
inline Points getContour () const;
|
inline Points getContour () const;
|
||||||
bool getAsRectangles ( std::vector<Box>& ) const;
|
bool getAsRectangles ( std::vector<Box>& ) const;
|
||||||
inline const vector<Point>& getPoints () const;
|
inline const vector<Point>& getPoints () const;
|
||||||
|
Box getNearestHSide ( DbU::Unit y ) const;
|
||||||
// Mutators.
|
// Mutators.
|
||||||
void setLayer ( const Layer* );
|
void setLayer ( const Layer* );
|
||||||
virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy );
|
virtual void translate ( const DbU::Unit& dx, const DbU::Unit& dy );
|
||||||
|
|
Loading…
Reference in New Issue