Fix offset track and extension problem in the H-Tree.

* Bug: In cumulus/plugins.block.htree._connectLeaf(), when HEAVY_LEAF_LOAD
    was used, the additionnal horizontal segment added to connect the
    extra buffer may have been:
    1. Misaligned, causing the blockage to be wrongly taken into account
       and leading to potential short circuits.
    2. In some RoutingGauge configurations, the extra length added to
       the segment left extention was too short, leading to DRC violations.
    So created new GaugeConf methods to manage thoses problems:
    * GaugeConf.getStackX() & GaugeConf.getStackY() to get back the
      contact coordinates of the *deep* part (typically the METAL2).
      So be able to align on them.
    * GaugeConf.createHorizontal(), added a parameter to explicitely
      state the additional length of the *left* extension. This is lazy,
      will soon add both.
This commit is contained in:
Jean-Paul Chaput 2021-11-02 10:30:33 +01:00
parent 53f019d165
commit dcc26f23c7
2 changed files with 102 additions and 9 deletions

View File

@ -245,22 +245,18 @@ class GaugeConf ( object ):
else: depth = self.verticalDepth
return self.getTrack( x, depth, offset )
def createHorizontal ( self, source, target, y, flags ):
def createHorizontal ( self, source, target, y, flags, dxSource=0 ):
if flags & GaugeConf.DeepDepth: depth = self.horizontalDeepDepth
else: depth = self.horizontalDepth
layer = self._routingGauge.getRoutingLayer(depth)
dxSource = 0
if flags & GaugeConf.SourceExtend: dxSource = self._routingGauge.getPitch(layer)
if not dxSource and flags & GaugeConf.SourceExtend:
dxSource = self._routingGauge.getPitch(layer)
if flags & GaugeConf.UseContactWidth:
width = source.getBoundingBox(layer.getBasicLayer()).getHeight()
else:
width = self._routingGauge.getLayerGauge(depth).getWireWidth()
if flags & GaugeConf.ExpandWidth:
width += DbU.fromLambda( 1.0 )
segment = Horizontal.create( source, target, layer, y, width )
segment.setDxSource( -dxSource )
trace( 550, segment )
@ -449,6 +445,98 @@ class GaugeConf ( object ):
self.expandMinArea( topContact )
return
def getStackY ( self, topContact, flags ):
"""
Get the Y coordinate of a stack contact, on the top level or in
the deep routing level.
:param topContact: The topmost contact of the VIA stack.
.. note:: A stacked contact is a set of contacts with short
segments to connect them. Segments are alternately
H & V, according to the routing gauge. Segments are
put on the routing tracks, so the X/Y coordinates
of the various contacts *may* slighlty vary.
"""
trace( 550, '\tgetStackY() {}\n'.format( topContact ))
y = topContact.getY()
lg = self.routingGauge.getLayerGauge( topContact.getLayer().getTop() )
if lg:
if lg.getDirection() == RoutingLayerGauge.Horizontal:
y = topContact.getY()
if not (flags & GaugeConf.DeepDepth):
return y
contact = topContact
depth = -1
while contact:
count = 0
segment = None
for component in contact.getSlaveComponents():
if isinstance(component,Horizontal):
horizontal = component
lg = self.routingGauge.getLayerGauge( horizontal.getLayer() )
if depth == -1 or lg.getDepth() < depth:
segment = horizontal
depth = lg.getDepth()
if isinstance(component,Vertical):
vertical = component
lg = self.routingGauge.getLayerGauge( vertical.getLayer() )
if depth == -1 or lg.getDepth() < depth:
segment = vertical
depth = lg.getDepth()
if not segment:
return y
if depth == self.horizontalDeepDepth:
return segment.getY()
contact = segment.getOppositeAnchor( contact )
return y
def getStackX ( self, topContact, flags ):
"""
Get the X coordinate of a stack contact, on the top level or in
the deep routing level.
:param topContact: The topmost contact of the VIA stack.
.. note:: A stacked contact is a set of contacts with short
segments to connect them. Segments are alternately
H & V, according to the routing gauge. Segments are
put on the routing tracks, so the X/Y coordinates
of the various contacts *may* slighlty vary.
"""
trace( 550, '\tgetStackX() {}\n'.format( topContact ))
x = topContact.getX()
lg = self.routingGauge.getLayerGauge( topContact.getLayer().getTop() )
if lg:
if lg.getDirection() == RoutingLayerGauge.Horizontal:
x = topContact.getX()
if not (flags & GaugeConf.DeepDepth):
return y
contact = topContact
depth = -1
while contact:
count = 0
segment = None
for component in contact.getSlaveComponents():
if isinstance(component,Horizontal):
horizontal = component
lg = self.routingGauge.getLayerGauge( horizontal.getLayer() )
if depth == -1 or lg.getDepth() < depth:
segment = horizontal
depth = lg.getDepth()
if isinstance(component,Vertical):
vertical = component
lg = self.routingGauge.getLayerGauge( vertical.getLayer() )
if depth == -1 or lg.getDepth() < depth:
segment = vertical
depth = lg.getDepth()
if not segment:
return x
if depth == self.verticalDeepDepth:
return segment.getX()
contact = segment.getOppositeAnchor( contact )
return x
def expandMinArea ( self, topContact ):
segments = []
contacts = [ topContact ]

View File

@ -96,14 +96,18 @@ class HTree ( object ):
hLeafDepth = gaugeConf.horizontalDepth - 2
gaugeConf.setStackPosition( contact, x, y )
gaugeConf.createVertical ( contact, forkContact, x, 0 )
trace( 550, '\tLeaf contact:{}\n'.format( contact ))
if len(leaf.buffers) > 1:
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input , ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input , ckNet )
tl2Y = gaugeConf.getTrack( tl2Contact.getY(), hLeafDepth, 2 )
left1X = gaugeConf.getNearestVerticalTrack( tl1Contact.getX(), 0, 0 )
left1Y = gaugeConf.getStackY( contact, GaugeConf.DeepDepth )
dxLeft = contact.getX() - gaugeConf.getStackX( contact, GaugeConf.DeepDepth )
gaugeConf.expandMinArea( tl2Contact )
gaugeConf.setStackPosition( tl1Contact, left1X , y )
gaugeConf.createHorizontal( contact , tl1Contact, y , GaugeConf.DeepDepth|GaugeConf.SourceExtend )
gaugeConf.setStackPosition( tl1Contact, left1X , left1Y )
#gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth|GaugeConf.SourceExtend )
gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth, dxLeft )
gaugeConf.createVertical ( contact , tl2Contact, x, 0 )
def _rrouteHTree ( self, qt ):
@ -173,6 +177,7 @@ class HTree ( object ):
if qt.tl:
self._connectLeaf( qt.tl, ckNet, leftContact, tlContact, leftX, tlY )
if qt.bl:
trace( 550, '\tConnect BL leaf, leftX={} blY={}\n'.format( DbU.getValueString(leftX), DbU.getValueString(blY) ))
self._connectLeaf( qt.bl, ckNet, leftContact, blContact, leftX, blY )
if qt.tr:
self._connectLeaf( qt.tr, ckNet, rightContact, trContact, rightX, tlY )