From dbb16b618f0f5444f350df38238b46500a41d2de Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Sun, 14 Mar 2021 16:16:54 +0100 Subject: [PATCH] Correct managment of macro block regarding to P&R. * Change: In NetBuilder::getPositions(), ordering of source/target points is now integrated to this function instead of left to the caller. In case of real (non-symbolic) routing gauge, skrink the ends of half the wire width. * Change: In NetBuilderHV::doRp_AutoContacts(), in case of non-METAL1 RoutingPad, put the axis of the segment on the nearest track. Issue a warning if we have to shift, as it may be a potential source of routing problems. * New: Anabatic::Session::getNearestTrackaAxis(), proxy to compute track positions, knowing the design abutment box. * Bug: In Katana::PreProcess::propagateCagedConstraints(), when looking at all the slave components anchoreds on a RoutingPad, if they do not have an AutoSegment lookup, skip them instead of crashing. * New: In cumulus/plugins.block.Block.placeMacro(), new method to place a macro cell, partly delegating to the Macro block wrapper. Must be called *after* both core and corona abutment boxes have been set. Adjust the macro block position so the METAL2 & METAL3 pins are exactly on pitch regarding the full routing grid. The reference being the corona. A shift, less than one pitch may be applied, leading in some cases of overlapping abutment boxes. But this shouldn't be a problem. The macro to place is designated through a path of instances names, rooted at the *core* (not the corona). Meaning that the head instance must be one of the core. * Change: In cumulus/plugins.chip.Chip, the complete chip I/O pads plus corona and core placement is moved out from doPnR() and put into doChipFloorplan(). It is now mandatory to call this method *before* doPnR(). Those methods are now cleanly separated so we can perform macro block placement or any inner core floorplaning operations between them. * Change: In cumulus/plugins.macro.Macro, instead of creating large pads for the I/O pins so whatever the block position, they will be under a grid point, create a simple dogleg to put them on grid. To ensure that they are "on grid", the block pins must be in METAL2 (horizontal E/W) or METAL3 (vertical N/S) and the block is assumed to be placed so the bottom left corner of it's abutment box is exactly on one grid point for M2/M3. This should be done by Block.placeMacro(). --- anabatic/src/NetBuilder.cpp | 42 +++- anabatic/src/NetBuilderHV.cpp | 50 ++++- anabatic/src/Session.cpp | 25 +++ anabatic/src/anabatic/Session.h | 3 + cumulus/src/plugins/alpha/block/block.py | 73 +++++++ cumulus/src/plugins/alpha/chip/chip.py | 34 ++- cumulus/src/plugins/alpha/macro/macro.py | 255 ++++++++++++++++------- katana/src/PreProcess.cpp | 3 +- 8 files changed, 373 insertions(+), 112 deletions(-) diff --git a/anabatic/src/NetBuilder.cpp b/anabatic/src/NetBuilder.cpp index a7a4144f..dda41455 100644 --- a/anabatic/src/NetBuilder.cpp +++ b/anabatic/src/NetBuilder.cpp @@ -228,22 +228,44 @@ namespace Anabatic { void NetBuilder::getPositions ( Component* anchor, Point& source, Point& target ) { - Segment* segment = dynamic_cast( anchor ); + Segment* segment = dynamic_cast( anchor ); if (segment) { source = segment->getSourcePosition(); target = segment->getTargetPosition(); - return; + } else { + RoutingPad* rp = dynamic_cast( anchor ); + if (rp) { + source = rp->getSourcePosition(); + target = rp->getTargetPosition(); + } else { + source = anchor->getPosition(); + target = anchor->getPosition(); + return; + } } - RoutingPad* rp = dynamic_cast( anchor ); - if (rp) { - source = rp->getSourcePosition(); - target = rp->getTargetPosition(); - return; - } + if (source == target) return; + if (source.getX() > target.getX()) swap( source, target ); + if (source.getY() > target.getY()) swap( source, target ); - source = anchor->getPosition(); - target = anchor->getPosition(); + if (not Session::getRoutingGauge()->isSymbolic()) { + size_t rpDepth = Session::getLayerDepth( anchor->getLayer() ); + Flags direction = Session::getDirection ( rpDepth ); + DbU::Unit wwidth = Session::getWireWidth (rpDepth) / 2; + cdebug_log(145,0) << "Not a symbolic gauge, shrink positions of " << DbU::getValueString(wwidth) << endl; + if (rpDepth == 0) return; + if (direction.contains(Flags::Horizontal)) { + cdebug_log(145,0) << "H shrink" << endl; + source.translate( wwidth, 0 ); + target.translate( -wwidth, 0 ); + } else { + cdebug_log(145,0) << "V shrink" << endl; + source.translate( 0, wwidth ); + target.translate( 0, -wwidth ); + } + } else { + cdebug_log(145,0) << "Symbolic gauge, no shrink" << endl; + } } diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp index dab61af8..bcc0d615 100644 --- a/anabatic/src/NetBuilderHV.cpp +++ b/anabatic/src/NetBuilderHV.cpp @@ -95,9 +95,6 @@ namespace Anabatic { getPositions( rp, sourcePosition, targetPosition ); - if (sourcePosition.getX() > targetPosition.getX()) swap( sourcePosition, targetPosition ); - if (sourcePosition.getY() > targetPosition.getY()) swap( sourcePosition, targetPosition ); - GCell* sourceGCell = Session::getAnabatic()->getGCellUnder( sourcePosition ); GCell* targetGCell = Session::getAnabatic()->getGCellUnder( targetPosition ); @@ -111,6 +108,53 @@ namespace Anabatic { if ( ((rpDepth != 0) or (sourcePosition == targetPosition)) and not (flags & NoProtect) ) { map::iterator irp = getRpLookup().find( rp ); if (irp == getRpLookup().end()) { + Box rpBb = rp->getBoundingBox(); + if (rpDepth != 0) { + DbU::Unit hborder = 0; + DbU::Unit vborder = 0; + if (direction.contains(Flags::Horizontal)) { + vborder = Session::getWireWidth(rpDepth) / 2; + rpBb.inflate( hborder, vborder ); + if (not rpBb.isEmpty()) { + DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer() + , sourcePosition.getY() + , Constant::Nearest ); + if (trackAxis != sourcePosition.getY()) { + cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust Y position to nearest H track of %s\n" + " (%s -> %s)" + , getString(rp).c_str() + , DbU::getValueString(sourcePosition.getY()).c_str() + , DbU::getValueString(trackAxis).c_str() + ) << endl; + sourcePosition.setY( trackAxis ); + targetPosition.setY( trackAxis ); + } + } else { + cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl; + } + } else { + hborder = Session::getWireWidth(rpDepth) / 2; + rpBb.inflate( hborder, vborder ); + if (not rpBb.isEmpty()) { + DbU::Unit trackAxis = Session::getNearestTrackAxis( rp->getLayer() + , sourcePosition.getX() + , Constant::Nearest ); + if (trackAxis != sourcePosition.getX()) { + cerr << Warning( "NetBuilderHV::doRp_AutoContacts(): Adjust X position to nearest V track of %s\n" + " (%s -> %s)" + , getString(rp).c_str() + , DbU::getValueString(sourcePosition.getX()).c_str() + , DbU::getValueString(trackAxis).c_str() + ) << endl; + sourcePosition.setX( trackAxis ); + targetPosition.setX( trackAxis ); + } + } else { + cdebug_log(145,0) << "rpBb is too narrow to adjust: " << rp->getBoundingBox() << endl; + } + } + } + AutoContact* sourceProtect = AutoContactTerminal::create( sourceGCell , rp , rpLayer diff --git a/anabatic/src/Session.cpp b/anabatic/src/Session.cpp index ea8e0a9b..6bc4639b 100644 --- a/anabatic/src/Session.cpp +++ b/anabatic/src/Session.cpp @@ -360,6 +360,31 @@ namespace Anabatic { } + DbU::Unit Session::_getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode ) + { + Box ab = _anabatic->getCell()->getAbutmentBox(); + + RoutingLayerGauge* lg = _routingGauge->getLayerGauge( layer ); + if (not lg) return axis; + + DbU::Unit minAxis = 0; + DbU::Unit maxAxis = 0; + if (lg->getDirection() == Constant::Horizontal) { + minAxis = ab.getYMin(); + maxAxis = ab.getYMax(); + } else { + minAxis = ab.getXMin(); + maxAxis = ab.getXMax(); + } + DbU::Unit trackAxis = lg->getTrackPosition( minAxis + , lg->getTrackIndex( minAxis + , maxAxis + , axis + , mode ) ); + return trackAxis; + } + + Point Session::_getNearestGridPoint ( Point p, Box constraint ) { Box ab = _anabatic->getCell()->getAbutmentBox(); diff --git a/anabatic/src/anabatic/Session.h b/anabatic/src/anabatic/Session.h index c87affd9..b708895c 100644 --- a/anabatic/src/anabatic/Session.h +++ b/anabatic/src/anabatic/Session.h @@ -132,6 +132,7 @@ namespace Anabatic { static inline DbU::Unit getWireWidth ( const Layer* ); static inline DbU::Unit getViaWidth ( const Layer* ); static inline DbU::Unit getExtensionCap ( const Layer* ); + static inline DbU::Unit getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode ); static inline Point getNearestGridPoint ( Point, Box constraints ); static inline size_t getSegmentStackSize (); static inline size_t getContactStackSize (); @@ -173,6 +174,7 @@ namespace Anabatic { void _revalidateTopology (); virtual size_t _revalidate (); DbU::Unit _getPitch ( size_t depth, Flags flags ) const; + DbU::Unit _getNearestTrackAxis ( const Layer*, DbU::Unit, uint32_t mode ); Point _getNearestGridPoint ( Point, Box constraints ); Record* _getRecord () const; string _getString () const; @@ -277,6 +279,7 @@ namespace Anabatic { inline DbU::Unit Session::getExtensionCap ( const Layer* layer ) { return getConfiguration()->getExtensionCap(layer); } inline Flags Session::getDirection ( const Layer* layer ) { return getDirection( getLayerDepth(layer) ); } inline Point Session::getNearestGridPoint ( Point p, Box b ) { return get("getNearestGridPoint()")->_getNearestGridPoint(p,b); } + inline DbU::Unit Session::getNearestTrackAxis ( const Layer* layer, DbU::Unit axis, uint32_t mode ) { return get("getNearestTrackAxis()")->_getNearestTrackAxis(layer,axis,mode); } inline void Session::_dogleg ( AutoSegment* segment ) { _doglegs.push_back(segment); } inline void Session::_doglegReset () { _doglegs.clear(); } diff --git a/cumulus/src/plugins/alpha/block/block.py b/cumulus/src/plugins/alpha/block/block.py index 68416fff..6b396014 100644 --- a/cumulus/src/plugins/alpha/block/block.py +++ b/cumulus/src/plugins/alpha/block/block.py @@ -32,6 +32,7 @@ import Anabatic import Katana import plugins.rsave from plugins import getParameter +from alpha.macro.macro import Macro from alpha.block import timing from alpha.block.spares import Spares from alpha.block.clocktree import ClockTree @@ -327,6 +328,34 @@ class Block ( object ): .format(self.conf.cell.getName()) ) Block.LUT[ self.conf.cell ] = self + @staticmethod + def _rgetInstance ( cell, path ): + """ + Get the instance designated by path (recursively). The path argument can be + either a string of instance names separated by dots or directly a list of + instances names. + """ + if isinstance(path,str): + path = path.split( '.' ) + elif not isinstance(path,list): + raise ErrorMessage( 1, 'Block._rgetInstance(): "path" argument is neither a string or a list ({})"' \ + .format(path) ) + instance = cell.getInstance( path[0] ) + if instance is None: + raise ErrorMessage( 1, 'Block._rgetInstance(): no instance "{}" in cell "{}"' \ + .format(path[0],cell.getName()) ) + if len(path) == 1: + return instance + return Block._rgetInstance( instance.getMasterCell(), path[1:] ) + + def rgetCoreInstance ( self, path ): + """ + Get the instance designated by path (recursively). The path argument can be + either a string of instance names separated by dots or directly a list of + instances names. The root of the path must be *core* cell. + """ + return Block._rgetInstance( self.conf.core, path ) + def setUnexpandPins ( self, sides ): """ Prevent Pins from the selected sides to be stick out of one pitch. @@ -551,6 +580,50 @@ class Block ( object ): Breakpoint.stop( 100, 'Placement done.' ) self.etesian.clearColoquinte() + def placeMacro ( self, ipath, transf ): + """ + Place the instance refered by ``ipath`` at position ``transformation``. + Both parameters are relative to the core cell. + """ + with UpdateSession(): + instance = self.rgetCoreInstance( ipath ) + macro = Macro.wrap( instance.getMasterCell() + , self.conf.routingGauge.getName(), 2, 2 ) + instanceAb = instance.getMasterCell().getAbutmentBox() + coreTransf = self.conf.icore.getTransformation() + if self.conf.isCoreBlock: + pnrAb = self.conf.icorona.getMasterCell().getAbutmentBox() + else: + pnrAb = self.conf.core.getAbutmentBox() + print( 'pnrAb={}'.format(pnrAb) ) + print( 'coreTransf={}'.format(coreTransf) ) + macroPosition = transf.getTranslation() + coreTransf.applyOn( macroPosition ) + xoffset = macroPosition.getX() - pnrAb.getXMin() + xpitch = self.conf.vDeepRG.getPitch() + print( 'Original X offset: {}'.format(DbU.getValueString(xoffset)) ) + if xoffset % xpitch: + xoffset += xpitch - (xoffset % xpitch) + print( 'Pitched X offset: {}'.format(DbU.getValueString(xoffset)) ) + yoffset = macroPosition.getY() - pnrAb.getYMin() + ypitch = self.conf.hDeepRG.getPitch() + print( 'Original Y offset: {}'.format(DbU.getValueString(yoffset)) ) + if yoffset % ypitch: + yoffset += ypitch - (yoffset % ypitch) + print( 'Pitched Y offset: {}'.format(DbU.getValueString(yoffset)) ) + macroPosition = Point( xoffset, yoffset ) + print( 'Position in corona={}'.format(macroPosition) ) + coreTransf.invert() + coreTransf.applyOn( macroPosition ) + print( 'Position in core={}'.format(macroPosition) ) + print( 'instanceAb={}'.format(instanceAb) ) + Macro.place( instance.getCell() + , instance + , Transformation( macroPosition.getX() + , macroPosition.getY() + , Transformation.Orientation.ID ) + , Instance.PlacementStatus.FIXED ) + def route ( self ): routedCell = self.conf.corona if self.conf.isCoreBlock else self.conf.cell self.katana = Katana.KatanaEngine.create( routedCell ) diff --git a/cumulus/src/plugins/alpha/chip/chip.py b/cumulus/src/plugins/alpha/chip/chip.py index afd95f31..ed8349a6 100644 --- a/cumulus/src/plugins/alpha/chip/chip.py +++ b/cumulus/src/plugins/alpha/chip/chip.py @@ -70,10 +70,20 @@ class Chip ( Block ): self.conf.validated = False return self.conf.validated - def doCoronaFloorplan ( self ): + def doChipFloorplan ( self ): + self.conf.computeCoronaBorder() + self.conf.chipValidate() if not self.conf.validated: - raise ErrorMessage( 1, 'chip.doCoronaFloorplan(): Chip is not valid, aborting.' ) - return + raise ErrorMessage( 1, 'chip.doChipFloorplan(): Chip is not valid, aborting.' ) + self.conf.chip.setAbutmentBox( self.conf.chipAb ) + trace( 550, '\tSet chip ab:{}\n'.format(self.conf.chip.getAbutmentBox()) ) + trace( 550, '\tUsing core ab:{}\n'.format(self.conf.core.getAbutmentBox()) ) + self.padsCorona = plugins.alpha.chip.pads.Corona( self.conf ) + self.conf.validated = self.padsCorona.validate() + if not self.conf.validated: + return False + self.padsCorona.doLayout() + self.validate() minHCorona = self.conf.minHCorona minVCorona = self.conf.minVCorona innerBb = Box( self.conf.coreAb ) @@ -98,6 +108,8 @@ class Chip ( Block ): y = y - (y % self.conf.sliceHeight) self.conf.icore.setTransformation ( Transformation(x,y,Transformation.Orientation.ID) ) self.conf.icore.setPlacementStatus( Instance.PlacementStatus.FIXED ) + self.padsCorona.doPowerLayout() + self.conf.refresh() def doConnectCore ( self ): if self.conf.routingGauge.hasPowerSupply(): @@ -119,22 +131,6 @@ class Chip ( Block ): self.conf.refresh() def doPnR ( self ): - self.conf.computeCoronaBorder() - self.conf.chipValidate() - if not self.conf.validated: - raise ErrorMessage( 1, 'chip.doChipPnR(): Chip is not valid, aborting.' ) - self.conf.chip.setAbutmentBox( self.conf.chipAb ) - trace( 550, '\tSet chip ab:{}\n'.format(self.conf.chip.getAbutmentBox()) ) - trace( 550, '\tUsing core ab:{}\n'.format(self.conf.core.getAbutmentBox()) ) - self.padsCorona = plugins.alpha.chip.pads.Corona( self.conf ) - self.conf.validated = self.padsCorona.validate() - if not self.conf.validated: - return False - self.padsCorona.doLayout() - self.validate() - self.doCoronaFloorplan() - self.padsCorona.doPowerLayout() - self.conf.refresh() super(Chip,self).doPnR() self.conf.refresh( self.conf.chip ) return self.conf.validated diff --git a/cumulus/src/plugins/alpha/macro/macro.py b/cumulus/src/plugins/alpha/macro/macro.py index 7f788864..c85e83ae 100644 --- a/cumulus/src/plugins/alpha/macro/macro.py +++ b/cumulus/src/plugins/alpha/macro/macro.py @@ -16,6 +16,7 @@ from __future__ import print_function import sys import os.path +from operator import itemgetter, attrgetter, methodcaller import Cfg from Hurricane import Breakpoint, DbU, Box, Transformation, Point, \ Box, Path, Layer, Occurrence, Net, \ @@ -43,22 +44,12 @@ class Macro ( object ): @staticmethod def lookup ( macroCell ): - if Macro.LUT.has_key(macroCell): return True - return False + if Macro.LUT.has_key(macroCell): return Macro.LUT[ macroCell ] + return None @staticmethod - def getPPitch ( rg, metal ): - depth = rg.getLayerDepth( metal ) - if depth < rg.getDepth(): pdepth = depth + 1 - else: pdepth = depth - 1 - return rg.getLayerPitch( pdepth ) - - @staticmethod - def getWireWidth ( rg, metal ): - return rg.getWireWidth( metal ) - - @staticmethod - def place ( instance, transf, status ): + def place ( topCell, instance, transf, status ): + macro = Macro.lookup( instance.getMasterCell() ) ab = instance.getMasterCell().getAbutmentBox() abShift = Transformation( -ab.getXMin(), -ab.getYMin(), Transformation.Orientation.ID ) abShift.applyOn( transf ) @@ -68,15 +59,48 @@ class Macro ( object ): @staticmethod def wrap ( macroCell, gaugeName, hMargin, vMargin ): """ - Encapsulate the macro cell, if not already done. Returns True - if the encapsulation actually takes place. + Adjust the interface of a macro block cell to better fit a + given routing gauge. Keep a table of the already processed + blocks (must be run only once for a block). + + For an explanation of the parameters, see Macro.__init__(). + """ + + macro = Macro.lookup( macroCell ) + if macro is not None: + return macro + return Macro( macroCell, gaugeName, hMargin, vMargin ) + + def getPPitch ( self, metal ): + depth = self.rg.getLayerDepth( metal ) + if depth < self.rg.getDepth(): pdepth = depth + 1 + else: pdepth = depth - 1 + return self.rg.getLayerPitch( pdepth ) + + def getWireWidth ( self, metal ): + return self.rg.getWireWidth( metal ) + + def getNearestTrackAxis ( self, metal, axis ): + lg = self.rg.getLayerGauge( metal ) + if lg.getDirection() == RoutingLayerGauge.Horizontal: + axisMin = self.outerAb.getYMin() + axisMax = self.outerAb.getYMax() + else: + axisMin = self.outerAb.getXMin() + axisMax = self.outerAb.getXMax() + trackIndex = lg.getTrackIndex( axisMin, axisMax, axis, RoutingLayerGauge.Nearest ) + return axisMin + lg.getOffset() + trackIndex * lg.getPitch() + + def __init__ ( self, macroCell, gaugeName, hMargin, vMargin ): + """ + Encapsulate a macro cell.to better fit the routing gauge. :param macroCell: The macro cell to be encapsulated. :param gaugeName: The name of the RoutingGauge to use. - :param xMargin: The horizontal margin, expressed in pitchs of the - lowest vertical routing metal (usually METAL3). - :param yMargin: The vertical margin, expressed in pitchs of the - lowesthorizontal routing metal (usually METAL2). + :param hMargin: The number of pitchs the horizontal terminals + will stick out of the original abutment box. + :param vMargin: The number of pitchs the vertical terminals + will stick out of the original abutment box. The abutment box of the block is enlarged so both it's dimensions are a multiple of the sliceHeight. It is then enlarged of one more @@ -88,17 +112,19 @@ class Macro ( object ): that are half free and half occluded by the block itself may cause (stupid) deadlock to appear. """ - if Macro.lookup(macroCell): return False + self.cell = macroCell + Macro.LUT[ self.cell ] = self af = CRL.AllianceFramework.get() - rg = af.getRoutingGauge( gaugeName ) - ab = macroCell.getAbutmentBox() + ab = self.cell.getAbutmentBox() + self.rg = af.getRoutingGauge( gaugeName ) + self.innerAb = ab sliceHeight = af.getCellGauge( gaugeName ).getSliceHeight() westPins = [] eastPins = [] northPins = [] southPins = [] - for net in macroCell.getNets(): + for net in self.cell.getNets(): if not net.isExternal() or net.isSupply() or net.isClock(): continue for component in net.getComponents(): @@ -111,114 +137,185 @@ class Macro ( object ): elif ab.getXMin() == bb.getXMin(): westPins.append( component ) elif ab.getYMax() == bb.getYMax(): northPins.append( component ) elif ab.getYMin() == bb.getYMin(): southPins.append( component ) - innerAb = ab xAdjust = 0 yAdjust = 0 if ab.getWidth () % sliceHeight: xAdjust = sliceHeight - ab.getWidth () % sliceHeight if ab.getHeight() % sliceHeight: yAdjust = sliceHeight - ab.getHeight() % sliceHeight - innerAb.inflate( 0, 0, xAdjust, yAdjust ) - outerAb = innerAb - outerAb.inflate( sliceHeight ) + self.innerAb.inflate( 0, 0, xAdjust, yAdjust ) + self.outerAb = self.innerAb + self.outerAb.inflate( sliceHeight ) + westPins .sort( key=lambda k: k.getBoundingBox().getYCenter() ) + eastPins .sort( key=lambda k: k.getBoundingBox().getYCenter() ) + northPins.sort( key=lambda k: k.getBoundingBox().getXCenter() ) + southPins.sort( key=lambda k: k.getBoundingBox().getXCenter() ) with UpdateSession(): for component in westPins: NetExternalComponents.setInternal( component ) - pitch = rg.getPitch( component.getLayer() ) - ppitch = Macro.getPPitch( rg, component.getLayer() ) - wwidth = Macro.getWireWidth( rg, component.getLayer() ) - bb = component.getBoundingBox() - yAxis = bb.getYCenter() - xMax = bb.getXMin() - xMin = xMax - hMargin*ppitch - width = bb.getHeight() + pitch = self.rg.getPitch( component.getLayer() ) + ppitch = self.getPPitch( component.getLayer() ) + wwidth = self.getWireWidth( component.getLayer() ) + bb = component.getBoundingBox() + yAxis = bb.getYCenter() + yOngrid = self.getNearestTrackAxis( component.getLayer(), yAxis ) + xMax = bb.getXMin() + xMin = xMax - hMargin*ppitch + width = bb.getHeight() + ppYAxis = yAxis + ppYOngrid = yOngrid + if not self.rg.isSymbolic(): + if ppYAxis < ppYOngrid: + ppYAxis -= width/2 + ppYOngrid += wwidth/2 + else: + ppYAxis += width/2 + ppYOngrid -= wwidth/2 + vertical = Vertical.create( component.getNet() + , component.getLayer() + , bb.getXMin() + , width + , ppYAxis + , ppYOngrid + ) horizontal = Horizontal.create( component.getNet() , component.getLayer() - , yAxis - , width + , yOngrid + , wwidth , xMin , xMax ) horizontal = Horizontal.create( component.getNet() , component.getLayer() - , yAxis - , pitch + wwidth + , yOngrid + , wwidth , xMin - , xMax - (hMargin-1) * ppitch + , xMax - ppitch ) NetExternalComponents.setExternal( horizontal ) for component in eastPins: NetExternalComponents.setInternal( component ) - pitch = rg.getPitch( component.getLayer() ) - ppitch = Macro.getPPitch( rg, component.getLayer() ) - wwidth = Macro.getWireWidth( rg, component.getLayer() ) - bb = component.getBoundingBox() - yAxis = bb.getYCenter() - xMin = innerAb.getXMax() - xMax = xMin + hMargin*ppitch - width = bb.getHeight() + pitch = self.rg.getPitch( component.getLayer() ) + ppitch = self.getPPitch( component.getLayer() ) + wwidth = self.getWireWidth( component.getLayer() ) + bb = component.getBoundingBox() + yAxis = bb.getYCenter() + yOngrid = self.getNearestTrackAxis( component.getLayer(), yAxis ) + xMin = self.innerAb.getXMax() + xMax = xMin + hMargin*ppitch + width = bb.getHeight() + ppYAxis = yAxis + ppYOngrid = yOngrid + if not self.rg.isSymbolic(): + if ppYAxis < ppYOngrid: + ppYAxis -= width/2 + ppYOngrid += wwidth/2 + else: + ppYAxis += width/2 + ppYOngrid -= wwidth/2 + vertical = Vertical.create( component.getNet() + , component.getLayer() + , bb.getXMax() + , width + , ppYAxis + , ppYOngrid + ) horizontal = Horizontal.create( component.getNet() , component.getLayer() - , yAxis - , width + , yOngrid + , pitch + wwidth , xMin , xMax ) horizontal = Horizontal.create( component.getNet() , component.getLayer() - , yAxis + , yOngrid , pitch + wwidth - , xMin + (hMargin-1) * ppitch + , xMin + ppitch , xMax ) NetExternalComponents.setExternal( horizontal ) for component in southPins: NetExternalComponents.setInternal( component ) - pitch = rg.getPitch( component.getLayer() ) - ppitch = Macro.getPPitch( rg, component.getLayer() ) - wwidth = Macro.getWireWidth( rg, component.getLayer() ) - bb = component.getBoundingBox() - xAxis = bb.getXCenter() - yMax = bb.getYMin() - yMin = xMax - vMargin*ppitch - width = bb.getWidth() + pitch = self.rg.getPitch( component.getLayer() ) + ppitch = self.getPPitch( component.getLayer() ) + wwidth = self.getWireWidth( component.getLayer() ) + bb = component.getBoundingBox() + xAxis = bb.getXCenter() + xOngrid = self.getNearestTrackAxis( component.getLayer(), xAxis ) + yMax = bb.getYMin() + yMin = yMax - vMargin*ppitch + width = bb.getWidth() + ppXAxis = xAxis + ppXOngrid = xOngrid + if not self.rg.isSymbolic(): + if ppXAxis < ppXOngrid: + ppXAxis -= width/2 + ppXOngrid += wwidth/2 + else: + ppXAxis += width/2 + ppXOngrid -= wwidth/2 + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , bb.getYMin() + , width + , ppXAxis + , ppXOngrid + ) vertical = Vertical.create( component.getNet() , component.getLayer() - , xAxis - , width + , xOngrid + , wwidth , yMin , yMax ) vertical = Vertical.create( component.getNet() , component.getLayer() - , xAxis - , pitch + wwidth + , xOngrid + , wwidth , yMin - , yMax - (vMargin-1) * ppitch + , yMax - ppitch ) NetExternalComponents.setExternal( vertical ) for component in northPins: NetExternalComponents.setInternal( component ) - pitch = rg.getPitch( component.getLayer() ) - ppitch = Macro.getPPitch( rg, component.getLayer() ) - wwidth = Macro.getWireWidth( rg, component.getLayer() ) - bb = component.getBoundingBox() - xAxis = bb.getXCenter() - yMin = innerAb.getYMax() - yMax = xMin + vMargin*ppitch - width = bb.getWidth() + pitch = self.rg.getPitch( component.getLayer() ) + ppitch = self.getPPitch( component.getLayer() ) + wwidth = self.getWireWidth( component.getLayer() ) + bb = component.getBoundingBox() + xAxis = bb.getXCenter() + xOngrid = self.getNearestTrackAxis( component.getLayer(), xAxis ) + yMin = self.innerAb.getYMax() + yMax = yMin + vMargin*ppitch + width = bb.getWidth() + ppXAxis = xAxis + ppXOngrid = xOngrid + if not self.rg.isSymbolic(): + if ppXAxis < ppXOngrid: + ppXAxis -= width/2 + ppXOngrid += wwidth/2 + else: + ppXAxis += width/2 + ppXOngrid -= wwidth/2 + horizontal = Horizontal.create( component.getNet() + , component.getLayer() + , bb.getYMax() + , width + , ppXAxis + , ppXOngrid + ) vertical = Vertical.create( component.getNet() , component.getLayer() - , xAxis - , width + , xOngrid + , pitch + wwidth , yMin , yMax ) vertical = Vertical.create( component.getNet() , component.getLayer() - , xAxis + , xOngrid , pitch + wwidth - , yMin + (vMargin-1) * ppitch + , yMin + ppitch , yMax ) NetExternalComponents.setExternal( vertical ) - macroCell.setAbutmentBox( outerAb ) + self.cell.setAbutmentBox( self.outerAb ) diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index d53e7a98..d91950db 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -183,8 +183,9 @@ namespace { TrackElement* parallel; for( Segment* osegment : rp->getSlaveComponents().getSubSet() ) { parallel = Session::lookup( osegment ); - cdebug_log(159,0) << "* " << parallel << endl; + if (not parallel) continue; + cdebug_log(159,0) << "* " << parallel << endl; if (parallel->isFixed ()) continue; if (parallel->isGlobal()) continue; getPerpandiculars( parallel, source, direction, perpandiculars );