Re-enable and check the building of I/O ring with pad spacers.
* New: In cumulus/block.bigvia, add a getBoundingBox() method. * New: In cumulus/block.configuration.GaugeConf.rpAccess(), add a vertical strap segment in case the RP is not high enough to accomodate the potential offset of the contact. In case of gauge with only two routing layers, if the RP is vertically accessed, do not put a VIA12 but just a METAL2 contact (there will be *no* turn). * Change: In cumulus/chip.CoreWire.drawWire(), the wire at *chip level* going to the pad was shrunk of 3 pitch when *not* in the preferred routing direction. Removing it as it creates gaps in some cases. This was likely needed for a specific kind of I/O pad so should be re-enabled on targeted cases in the future. * Change: In cumulus/chip.corona.VerticalRail, manage in a smarter way the conflicts when a rail is accessed from both sides overlapping on an Y position. That is, from the supply I/O pads *and* from the *core* supply lines. Formerly, we just didn't connect the core power line, which was a mistake potentially leaving power rails unconnected (it it did occur on both sides). Also checks if the conflict really arise, that is, the power lines are both on top or bottom. * Change: In cumulus/chip.pads.Side._placePad(), manage I/O pads with a bottom left corner of abutment box *not* at (0,0). Argh! * Bug: In cumulus/chip.pads, create the filler pad instances in the chip, not in the corona.
This commit is contained in:
parent
0e17b91692
commit
181b2e1080
|
@ -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():
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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() )
|
||||
|
|
|
@ -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 '<HorizontalRail "{}" ({}) @{}>'.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) )
|
||||
|
|
|
@ -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(?P<power>v[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:
|
||||
|
|
Loading…
Reference in New Issue