From dcc26f23c749ea15566c3807e4aca65d5152fcf6 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Tue, 2 Nov 2021 10:30:33 +0100 Subject: [PATCH] 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. --- .../src/plugins/alpha/block/configuration.py | 102 ++++++++++++++++-- cumulus/src/plugins/alpha/block/htree.py | 9 +- 2 files changed, 102 insertions(+), 9 deletions(-) diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index 006b07f3..51c2d306 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -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 ] diff --git a/cumulus/src/plugins/alpha/block/htree.py b/cumulus/src/plugins/alpha/block/htree.py index 0ed4422a..e710302c 100644 --- a/cumulus/src/plugins/alpha/block/htree.py +++ b/cumulus/src/plugins/alpha/block/htree.py @@ -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 )