diff --git a/cumulus/src/plugins/alpha/block/bigvia.py b/cumulus/src/plugins/alpha/block/bigvia.py index e3f2cfff..a395e915 100644 --- a/cumulus/src/plugins/alpha/block/bigvia.py +++ b/cumulus/src/plugins/alpha/block/bigvia.py @@ -89,6 +89,12 @@ class BigVia ( object ): def getNet ( self ): return self.net + def getBoundingBox ( self, depth ): + bb = Box( self.x, self.y ) + bb.inflate( self.widths[depth] // 2, self.heights[depth] // 2 ) + return bb + + def getPlate ( self, metal ): if not self.hasLayout: return None for plate in self.plates.values(): diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index 6711f8a8..cf0c02aa 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -319,21 +319,60 @@ class GaugeConf ( object ): if flags & GaugeConf.OffsetTop2: yoffset = -2 trace( 550, '\tyoffset:{}\n'.format(yoffset) ) if startDepth == 0: - contact1 = Contact.create( rp, self._routingGauge.getContactLayer(0), 0, 0 ) - ytrack = self.getTrack( contact1.getY(), self.horizontalDeepDepth, yoffset ) - dy = ytrack - contact1.getY() - trace( 550, '\tPut on Y-tracks:{}\n'.format(DbU.getValueString(ytrack)) ) - contact1.setDy( dy ) + rg = self.routingGauge.getLayerGauge( 0 ) + rpContact = Contact.create( rp, rg.getLayer(), 0, 0 ) + ytrack = self.getTrack( rpContact.getY(), self.horizontalDeepDepth, yoffset ) + contact1 = Contact.create( rp.getNet() + , self._routingGauge.getContactLayer( 0 ) + , rpContact.getX() + , ytrack + , rg.getViaWidth() + , rg.getViaWidth() + ) + segment = Vertical.create( rpContact + , contact1 + , rpContact.getLayer() + , rpContact.getX() + , rg.getWireWidth() + ) + #dy = ytrack - contact1.getY() + #trace( 550, '\tPut on Y-tracks:{}\n'.format(DbU.getValueString(ytrack)) ) + #contact1.setDy( dy ) else: - contact1 = Contact.create( rp, self._routingGauge.getContactLayer(startDepth), 0, 0 ) - ytrack = self.getTrack( contact1.getY(), startDepth, 0 ) - dy = ytrack - contact1.getY() + rg = self.routingGauge.getLayerGauge( startDepth ) + rpContact = Contact.create( rp, rg.getLayer(), 0, 0 ) + ytrack = self.getTrack( rpContact.getY(), startDepth, 0 ) + #dy = ytrack - contact1.getY() + contact1 = Contact.create( rp.getNet() + , self._routingGauge.getContactLayer( startDepth ) + , rpContact.getX() + , ytrack + , rg.getViaWidth() + , rg.getViaWidth() + ) + segment = Vertical.create( rpContact + , contact1 + , rpContact.getLayer() + , rpContact.getX() + , rg.getWireWidth() + ) + trace( 550, '\trpContact:{}\n'.format( rpContact )) + trace( 550, '\tcontact1: {}\n'.format( contact1 )) + trace( 550, '\tsegment: {}\n'.format( segment )) startDepth += 1 - trace( 550, contact1 ) + trace( 550, '\tcontact1={}\n'.format( contact1 )) if flags & GaugeConf.HAccess: stopDepth = hdepth else: stopDepth = vdepth - trace( 550, '\tstopDepth:%d\n' % stopDepth ) + trace( 550, '\trange(startDepth={},stopDepth={})={}\n' \ + .format( startDepth, stopDepth, list(range(startDepth,stopDepth)) )) + + if startDepth >= stopDepth: + if not flags & GaugeConf.HAccess: + contact1.setLayer( rpContact.getLayer() ) + self._rpToAccess[rp] = contact1 + trace( 550, '-' ) + return contact1 for depth in range(startDepth,stopDepth): rg = self.routingGauge.getLayerGauge(depth) diff --git a/cumulus/src/plugins/alpha/block/htree.py b/cumulus/src/plugins/alpha/block/htree.py index f0ae35fe..92b2932b 100644 --- a/cumulus/src/plugins/alpha/block/htree.py +++ b/cumulus/src/plugins/alpha/block/htree.py @@ -154,12 +154,13 @@ class HTree ( object ): ckParentNet = qt.bInputPlug(0).getNet() driverContact = gaugeConf.rpAccessByPlugName( qt.buffers[0], bufferConf.input, ckParentNet ) driverY = driverContact.getY() + trace( 550, '\tdriverContact={}\n'.format( driverContact )) if qt.bl: trace( 550, '+,', '\tblContact\n' ) blContact = gaugeConf.rpAccessByPlugName( qt.bl.buffers[0], bufferConf.input, ckNet, GaugeConf.OffsetLeft1 ) trace( 550, ',-', '\tblContact={}\n'.format(blContact) ) if qt.br: - trace( 550, '+,', '\trlContact\n' ) + trace( 550, '+,', '\tbrContact\n' ) brContact = gaugeConf.rpAccessByPlugName( qt.br.buffers[0], bufferConf.input, ckNet, GaugeConf.OffsetLeft1 ) trace( 550, ',-', '\tbrContact={}\n'.format(brContact) ) if qt.tl: diff --git a/cumulus/src/plugins/alpha/chip/__init__.py b/cumulus/src/plugins/alpha/chip/__init__.py index adc1cd23..38adf3d1 100644 --- a/cumulus/src/plugins/alpha/chip/__init__.py +++ b/cumulus/src/plugins/alpha/chip/__init__.py @@ -203,9 +203,11 @@ class CoreWire ( object ): coronaAb = self.conf.getInstanceAb( self.conf.icorona ) coronaTransf = self.conf.icorona.getTransformation() self._computeCoreLayers() + trace( 550, '\tbbSegment: {}\n'.format(self.bbSegment) ) padLayer = self.padSegment.getLayer() if not isinstance(padLayer,BasicLayer): padLayer = padLayer.getBasicLayer() + trace( 550, '\tpadLayer={}\n'.format( padLayer )) if self.side == West or self.side == East: flags = OnHorizontalPitch hPitch = self.conf.getPitch( self.symSegmentLayer ) @@ -222,18 +224,20 @@ class CoreWire ( object ): xContact = self.corona.coreSymBb.getXMin() - self.offset * 2*vPitch xPadMax = xContact xCore = coronaAb.getXMin() - if not self.preferredDir: - #xPadMax += self.bbSegment.getHeight()//2 - xPadMin += 3*vPitch + trace( 550, '\txPadMin: {}\n'.format(DbU.getValueString( xPadMin ))) + #if not self.preferredDir: + # #xPadMax += self.bbSegment.getHeight()//2 + # xPadMin += 3*vPitch + # trace( 550, '\txPadMin: {}\n'.format(DbU.getValueString( xPadMin ))) else: accessDirection = Pin.Direction.EAST xPadMax = self.bbSegment.getXMax() xContact = self.corona.coreSymBb.getXMax() + self.offset * 2*vPitch xPadMin = xContact xCore = coronaAb.getXMax() - vPitch - if not self.preferredDir: - #xPadMin -= self.bbSegment.getHeight()//2 - xPadMin -= 3*vPitch + #if not self.preferredDir: + # #xPadMin -= self.bbSegment.getHeight()//2 + # xPadMin -= 3*vPitch if self.addJumper: rg = self.conf.routingGauge gaugeM5 = rg.getLayerGauge( 4 ) @@ -296,6 +300,7 @@ class CoreWire ( object ): , xPadMin , xPadMax ) + trace( 550, '\thChip={}\n'.format( hChip )) trace( 550, '\tself.arraySize: %s\n' % str(self.arraySize) ) if self.arraySize: contacts = self.conf.coronaContactArray( self.chipNet @@ -331,6 +336,7 @@ class CoreWire ( object ): , xContact , xCore ) + trace( 550, '\thCorona={}\n'.format( hCorona )) trace( 550, '\tCORONA PIN: {} {}\n'.format(self.chipNet, self.count) ) pin = self.conf.coronaPin( self.chipNet , self.count @@ -342,22 +348,26 @@ class CoreWire ( object ): , self.bbSegment.getHeight() ) hChipBb = hChip.getBoundingBox( padLayer ) + trace( 550, '\thChipBb={}\n'.format( hChipBb )) vStrapBb.merge( vStrapBb.getXMin(), hChipBb.getYMin() ) vStrapBb.merge( vStrapBb.getXMin(), hChipBb.getYMax() ) - hCoronaBb = hCorona.getBoundingBox( padLayer ) + #hCoronaBb = hCorona.getBoundingBox( padLayer ) + hCoronaBb = hCorona.getBoundingBox() self.conf.icorona.getTransformation().applyOn( hCoronaBb ) + trace( 550, '\thCoronaBb={}\n'.format( hCoronaBb )) vStrapBb.merge( vStrapBb.getXMin(), hCoronaBb.getYMin() ) vStrapBb.merge( vStrapBb.getXMin(), hCoronaBb.getYMax() ) if self.padSegment.getLayer().isSymbolic(): vStrapBb.inflate( 0, -self.padSegment.getLayer().getExtentionCap() , 0, -self.padSegment.getLayer().getExtentionCap() ) - Vertical.create( self.chipNet - , self.padSegment.getLayer() - , vStrapBb.getCenter().getX() - , vStrapBb.getWidth() - , vStrapBb.getYMin() - , vStrapBb.getYMax() - ) + v = Vertical.create( self.chipNet + , self.padSegment.getLayer() + , vStrapBb.getCenter().getX() + , vStrapBb.getWidth() + , vStrapBb.getYMin() + , vStrapBb.getYMax() + ) + trace( 550, '\tvChip={}\n'.format( v )) else: flags = OnVerticalPitch hPitch = self.conf.getPitch( self.padSegment.getLayer() ) diff --git a/cumulus/src/plugins/alpha/chip/corona.py b/cumulus/src/plugins/alpha/chip/corona.py index 1ca8cb0d..65e41802 100644 --- a/cumulus/src/plugins/alpha/chip/corona.py +++ b/cumulus/src/plugins/alpha/chip/corona.py @@ -13,8 +13,9 @@ # +-----------------------------------------------------------------+ +import sys import bisect -from operator import methodcaller +from operator import methodcaller, xor import Cfg from Hurricane import DbU, Point, Interval, Box, Transformation, \ Path, Occurrence, Net, Contact, Horizontal, \ @@ -100,8 +101,7 @@ class HorizontalRail ( Rail ): return ''.format( self.side.getRailNet(self.order).getName() , self.order , DbU.getValueString(self.axis) ) - - def connect ( self, contact ): + def isReachable ( self, contact ): trace( 550, ',+', '\tTry to connect to: {}\n'.format(self) ) trace( 550, '\tContact {}\n'.format(contact) ) contactBb = contact.getBoundingBox() @@ -132,6 +132,10 @@ class HorizontalRail ( Rail ): trace( 550, ',-', '\tFailed: overlap with existing contact @{}.\n' \ .format(self.vias[keys[insertIndex-1]][2]) ) return False + trace( 550, ',-' ) + return True + + def connect ( self, contact ): viaWidth = contact.getWidth() viaHeight = self.side.hRailWidth if self.conf.routingGauge.isSymbolic(): @@ -152,7 +156,6 @@ class HorizontalRail ( Rail ): , DbU.getValueString(contact.getX()) , DbU.getValueString(self.axis)) ) self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) - trace( 550, '-' ) return True def doLayout ( self ): @@ -218,8 +221,11 @@ class VerticalRail ( Rail ): , self.side.vRailWidth ) - def connect ( self, contact ): - contactBb = contact.getBoundingBox() + def isReachable ( self, contact ): + railDepth = self.conf.routingGauge.getLayerDepth( self.side.getVLayer() ) + contactDepth = self.conf.routingGauge.getLayerDepth( contact.getLayer() ) + contactBb = contact.getBoundingBox() + contactAbove = True if contactDepth > railDepth else False if contactBb.getYMin() < self.side.innerBb.getYMin() \ or contactBb.getYMax() > self.side.innerBb.getYMax(): # XXX turn this into a non-fatal case. ERROR is still printed, @@ -228,7 +234,7 @@ class VerticalRail ( Rail ): , 'power pad is likely to be to far off north or south.' , '(core:{})'.format(self.side.innerBb) ] ) ) if contact.getY() in self.vias: return False - trace( 550, ',+', '\tVerticalRail.connect() [{}] @{}\n'.format(self.order,DbU.getValueString(self.axis)) ) + trace( 550, ',+', '\tVerticalRail.isReachable() [{}] @{}\n'.format(self.order,DbU.getValueString(self.axis)) ) trace( 550, '\t{}\n'.format(contact) ) keys = list( self.vias.keys() ) keys.sort() @@ -241,20 +247,43 @@ class VerticalRail ( Rail ): if len(keys) > 0: if insertIndex < len(keys): insertPosition = keys[ insertIndex ] - trace( 550, '\tinsertIndex:{}'.format(insertIndex) ) + trace( 550, '\tinsertIndex:{}\n'.format(insertIndex) ) trace( 550, '\tCheck NEXT contactBb:{} via:{}\n' \ .format( contactBb - , self.vias[insertPosition][2].getBoundingBox()) ) - if contactBb.getYMax() >= self.vias[insertPosition][2].getBoundingBox().getYMin(): + , self.vias[insertPosition][1].getBoundingBox(railDepth)) ) + if self.vias[insertPosition][1].bottomDepth < railDepth: bigviaAbove = False + elif self.vias[insertPosition][1].topDepth > railDepth: bigviaAbove = True + else: + print( ErrorMessage( 1, [ '{} neither above nor below' \ + .format( self.vias[insertPosition][1] ) ] )) + trace( 550, '\tcontactAbove={} bigviaAbove={}\n'.format( contactAbove, bigviaAbove )) + if contactBb.getYMax() >= self.vias[insertPosition][1].getBoundingBox(railDepth).getYMin() \ + and not xor(contactAbove,bigviaAbove): trace( 550, ',--', '\tReject {} intersect NEXT\n'.format(contact) ) return False if insertIndex > 0: + insertPosition = keys[ insertIndex-1 ] trace( 550, '\tcheck PREVIOUS contactBb:{} via:{}\n' \ .format( contactBb - , self.vias[keys[insertIndex-1]][2].getBoundingBox()) ) - if self.vias[keys[insertIndex-1]][2].getBoundingBox().getYMax() >= contactBb.getYMin(): + , self.vias[insertPosition][1].getBoundingBox(railDepth)) ) + if self.vias[insertPosition][1].bottomDepth < railDepth: bigviaAbove = False + elif self.vias[insertPosition][1].topDepth > railDepth: bigviaAbove = True + else: + print( ErrorMessage( 1, [ '{} neither above nor below' \ + .format( self.vias[insertPosition][1] ) ] )) + trace( 550, '\tcontactAbove={} bigviaAbove={}\n'.format( contactAbove, bigviaAbove )) + if self.vias[insertPosition][1].getBoundingBox(railDepth).getYMax() >= contactBb.getYMin() \ + and not xor(contactAbove,bigviaAbove): trace( 550, ',--', '\tReject {} intersect PREVIOUS\n'.format(contact) ) return False + trace( 550, ',--' ) + return True + + def connect ( self, contact ): + trace( 550, '\tVerticalRail.connect() {}\n'.format(contact) ) + if self.net != contact.getNet(): + trace( 550, '\tReject {} vs. {}\n'.format( self.net, contact.getNet() )) + return False viaWidth = self.side.vRailWidth viaHeight = contact.getHeight() if self.conf.routingGauge.isSymbolic(): @@ -269,8 +298,8 @@ class VerticalRail ( Rail ): , contact.getHeight() - DbU.fromLambda(1.0) , flags=BigVia.AllowAllExpand ) , contact ] - trace(550, ',--' '\tADD {}\n'.format(contact) ) self.vias[ contact.getY() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) + trace( 550, '\t-> BigVIA {}\n'.format(self.vias[ contact.getY() ][1]) ) return True @@ -348,15 +377,18 @@ class Side ( object ): for terminal in blockSide.terminals: trace( 550, '\tterminal:{}\n'.format(terminal) ) for rail in self.rails: + if not rail.isReachable( terminal[1] ): + break rail.connect( terminal[1] ) def getRailRange ( self, net ): if net.isClock(): return range(len(self.rails)) if not net.isSupply(): return [] if self.side & HORIZONTAL: - trace( 550, '\tHORIZONTAL rail.\n' ) + trace( 550, '\tHorizontal rail.\n' ) return range( len(self.coronaCks), len(self.rails) ) else: + trace( 550, '\tVertical rail.\n' ) trace( 550, '\t{} > {}\n'.format(self.horizontalDepth,self.verticalDepth) ) if self.horizontalDepth > self.verticalDepth: return range( len(self.coronaCks), len(self.rails) ) diff --git a/cumulus/src/plugins/alpha/chip/pads.py b/cumulus/src/plugins/alpha/chip/pads.py index 50fd9eff..5334ea52 100644 --- a/cumulus/src/plugins/alpha/chip/pads.py +++ b/cumulus/src/plugins/alpha/chip/pads.py @@ -150,7 +150,7 @@ class Corner ( object ): def _instanciateCorner ( self ): name, transformation = self._getTransformation() - corner = Instance.create( self.conf.cell + corner = Instance.create( self.conf.chip , name, self.corona.padCorner , transformation , Instance.PlacementStatus.FIXED @@ -278,7 +278,7 @@ class Side ( object ): iPadSpacer = _nextSpacer( iPadSpacer ) while iPadSpacer < len(self.corona.padSpacers) and gapWidth > 0: gapWidth -= _getWidth( self.corona.padSpacers[iPadSpacer] ) - spacer = Instance.create( self.conf.cell + spacer = Instance.create( self.conf.chip , self.spacerNames % self.spacerCount , self.corona.padSpacers[iPadSpacer]) self.spacerCount += 1 @@ -286,13 +286,14 @@ class Side ( object ): if gapWidth < _getWidth(self.corona.padSpacers[iPadSpacer]): iPadSpacer = _nextSpacer( iPadSpacer ) if gapWidth != 0: - raise ErrorMessage( 1, 'PadsCorona.Side._placePads(): Pad fillers cannot close the gap between pads on {} side, {} remains.' \ - .format(self.sideName,DbU.getValueString(gapWidth)) ) + print( ErrorMessage( 1, 'PadsCorona.Side._placePads(): Pad fillers cannot close the gap between pads on {} side, {} remains.' \ + .format(self.sideName,DbU.getValueString(gapWidth)) )) self.u += gapWidth def _placePad ( self, padInstance ): + padAb = padInstance.getMasterCell().getAbutmentBox() if self.type == North: - x = self.conf.chipAb.getXMin() + self.u + x = self.conf.chipAb.getXMin() + self.u - padAb.getXMin() y = self.conf.chipAb.getYMax() if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.MY @@ -301,7 +302,7 @@ class Side ( object ): y -= self.conf.ioPadHeight x = self.toGrid( x ) elif self.type == South: - x = self.conf.chipAb.getXMin() + self.u + x = self.conf.chipAb.getXMin() + self.u - padAb.getXMin() y = self.conf.chipAb.getYMin() if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.ID @@ -311,27 +312,29 @@ class Side ( object ): x = self.toGrid( x ) elif self.type == West: x = self.conf.chipAb.getXMin() - y = self.conf.chipAb.getYMin() + self.u + y = self.conf.chipAb.getYMin() + self.u + padAb.getXMin() if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.R3 - y += padInstance.getMasterCell().getAbutmentBox().getWidth() + y += padAb.getWidth() else: orientation = Transformation.Orientation.R1 - x += padInstance.getMasterCell().getAbutmentBox().getHeight() + x += padAb.getHeight() y = self.toGrid( y ) elif self.type == East: x = self.conf.chipAb.getXMax() y = self.conf.chipAb.getYMin() + self.u + if padAb.getXMin(): + y += padAb.getXMin() + padAb.getWidth() if self.corona.padOrient == Transformation.Orientation.ID: orientation = Transformation.Orientation.R1 else: orientation = Transformation.Orientation.R3 - x -= padInstance.getMasterCell().getAbutmentBox().getHeight() - y += padInstance.getMasterCell().getAbutmentBox().getWidth() + x -= padAb.getHeight() + y += padAb.getWidth() y = self.toGrid( y ) padInstance.setTransformation ( Transformation( x, y, orientation ) ) padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED ) - self.u += padInstance.getMasterCell().getAbutmentBox().getWidth() + self.u += padAb.getWidth() p = None if self.conf.ioPadGauge.getName() == 'pxlib': p = re.compile( r'p(?Pv[sd]{2}[ei])ck_px' ) @@ -510,12 +513,15 @@ class Corona ( object ): def __init__ ( self, chip ): - def _cmpPad ( pad1, pad2): - width1 = pad1.getAbutmentBox().getWidth() - width2 = pad2.getAbutmentBox().getWidth() - if width1 == width2: return 0 - if width1 > width2: return -1 - return 1 + def _cmpPad ( pad ): + return pad.getAbutmentBox().getWidth() + + #def _cmpPad ( pad1, pad2): + # width1 = pad1.getAbutmentBox().getWidth() + # width2 = pad2.getAbutmentBox().getWidth() + # if width1 == width2: return 0 + # if width1 > width2: return -1 + # return 1 def _dupPads ( padsConf ): duplicateds = [] @@ -560,7 +566,7 @@ class Corona ( object ): if spacerCell: self.padSpacers.append( spacerCell ) else: raise ErrorMessage( 1, 'Corona.__init__(): Missing spacer cell "{}"'.format(spacerName) ) - self.padSpacers.sort( _cmpPad ) + self.padSpacers = sorted( self.padSpacers, key=_cmpPad, reverse=True ) if self.conf.cfg.chip.padCorner is not None: self.padCorner = self.padLib.getCell( self.conf.cfg.chip.padCorner ) if self.conf.cfg.chip.minPadSpacing is None: