diff --git a/cumulus/src/plugins/alpha/block/block.py b/cumulus/src/plugins/alpha/block/block.py index 988960fe..4c499025 100644 --- a/cumulus/src/plugins/alpha/block/block.py +++ b/cumulus/src/plugins/alpha/block/block.py @@ -401,7 +401,7 @@ class Block ( object ): print( ' o Building clock tree(s).' ) af = CRL.AllianceFramework.get() clockNets = [] - for net in self.conf.cell.getNets(): + for net in self.conf.cellPnR.getNets(): if af.isCLOCK(net.getName()): 'CLOCK: {}'.format(net) if net.isClock(): trace( 550, '\tBlock.addClockTrees(): Found clock {}.\n'.format(net) ) @@ -592,6 +592,7 @@ class Block ( object ): break if self.conf.useClockTree: self.splitClocks() if self.conf.isCoreBlock: self.doConnectCore() + self.spares.removeUnusedBuffers() status = self.route() if not self.conf.isCoreBlock: self.addBlockages() diff --git a/cumulus/src/plugins/alpha/block/clocktree.py b/cumulus/src/plugins/alpha/block/clocktree.py index b18757c6..c693dfbd 100644 --- a/cumulus/src/plugins/alpha/block/clocktree.py +++ b/cumulus/src/plugins/alpha/block/clocktree.py @@ -82,6 +82,7 @@ class ClockTree ( object ): if qt.isLeaf(): return False qt.rconnectBuffer() driverNet = qt.bOutputPlug.getNet() + driverNet.setType( Net.Type.CLOCK ) for leaf in qt.leafs: leaf.bInputPlug.setNet( driverNet ) self._rconnectHTree( leaf ) @@ -135,13 +136,13 @@ class ClockTree ( object ): gaugeConf.createVertical ( trContact , rightContact , rightX , 0 ) if qt.isRoot(): ckNet = self.clockNet - trace( 550, '\tRemoving any previous pin...\n' ) - pins = [] - for pin in ckNet.getPins(): pins.append( pin ) - for pin in pins: - print( WarningMessage('ClockTree._rrouteHTree(): Removing {}.'.format(pin)) ) - pin.destroy() if not self.spares.conf.isCoreBlock: + trace( 550, '\tRemoving any previous pin...\n' ) + pins = [] + for pin in ckNet.getPins(): pins.append( pin ) + for pin in pins: + print( WarningMessage('ClockTree._rrouteHTree(): Removing {}.'.format(pin)) ) + pin.destroy() layerGauge = gaugeConf.vRoutingGauge rootContact = gaugeConf.rpAccessByPlugName( qt.buffer, bufferConf.input, ckNet, 0 ) x = gaugeConf.getNearestVerticalTrack ( qt.area, rootContact.getX(), 0 ) @@ -187,14 +188,19 @@ class ClockTree ( object ): quadTree.bufferTag = self.clockNet.getName() quadTree.rselectBuffer( self.clockIndex, self.clockIndex, 0 ) with UpdateSession(): - hyperClock = HyperNet.create( Occurrence(self.clockNet) ) + coronaPlugs = [] + hyperClock = HyperNet.create( Occurrence(self.clockNet) ) for plugOccurrence in hyperClock.getTerminalNetlistPlugOccurrences(): - quadTree.attachToLeaf( plugOccurrence ) + if quadTree.isUnderArea(plugOccurrence): + quadTree.attachToLeaf( plugOccurrence ) + else: + coronaPlugs.append( plugOccurrence ) quadTree.rsplitNetlist() if self.spares.conf.isCoreBlock: plug = utils.getPlugByName( quadTree.buffer, bufferConf.input ) plug.setNet( self.clockNet ) trace( 550, '\tCore mode, setting only root plug "{}"\n'.format(self.clockNet.getName()) ) - trace( 550, '\tPlug of "{}"\n'.format(self.clockNet.getName()) ) + trace( 550, '\tPlug of "{}" (Cell:{})\n'.format(self.clockNet.getName() + ,self.clockNet.getCell()) ) for plug in self.clockNet.getPlugs(): trace( 550, '\t| {}\n'.format(plug) ) diff --git a/cumulus/src/plugins/alpha/block/configuration.py b/cumulus/src/plugins/alpha/block/configuration.py index b39836d5..fb298298 100644 --- a/cumulus/src/plugins/alpha/block/configuration.py +++ b/cumulus/src/plugins/alpha/block/configuration.py @@ -16,6 +16,7 @@ from __future__ import print_function import sys import re import os.path +from operator import itemgetter import Cfg from Hurricane import Breakpoint from Hurricane import DbU @@ -596,6 +597,67 @@ class BufferInterface ( object ): self.count = 0 +# ---------------------------------------------------------------------------- +# Class : "configuration.FeedsConf". + +class FeedsConf ( object ): + """ + Store informations about feed cells and how to fill a gap. + """ + + def __init__ ( self, framework ): + trace( 550, ',+', '\tFeedsConf.__init__()\n' ) + feeds = Cfg.getParamString('etesian.feedNames').asString().split(',') + self.count = 0 + self.feeds = [] + for feedName in feeds: + feedCell = framework.getCell( feedName, CRL.Catalog.State.Views ) + if not feedCell: + print( WarningMessage( 'FeedConf.__init__(): Feed cell "{}" not found in library (skipped).' \ + .format(feedName)) ) + continue + feedWidth = feedCell.getAbutmentBox().getWidth() + self.feeds.append( (feedWidth,feedCell) ) + self.feeds.sort( key=itemgetter(0) ) + self.feeds.reverse() + print( self.feeds ) + for i in range(len(self.feeds)): + trace( 550, '\t[{:>2}] {:>10} {}\n' \ + .format(i,DbU.getValueString(self.feeds[i][0]),self.feeds[i][1]) ) + trace( 550, '-' ) + return + + def fillAt ( self, cell, transf, gapWidth ): + """ + In ``cell``, fill a *one* row gap starting at ``transf`` position and + of length ``gapWidth``. + """ + x = transf.getTx() + while gapWidth > 0: + feedAdded = False + for i in range(len(self.feeds)): + if self.feeds[i][0] <= gapWidth: + instance = Instance.create( cell, 'spare_feed_{}'.format(self.count), self.feeds[i][1] ) + instance.setTransformation( Transformation( x + , transf.getTy() + , transf.getOrientation() )) + instance.setPlacementStatus( Instance.PlacementStatus.FIXED ) + gapWidth -= self.feeds[i][0] + x += self.feeds[i][0] + self.count += 1 + feedAdded = True + if not feedAdded: break + if gapWidth > 0: + print( WarningMessage( [ 'FeedConf.fillAt(): Unable to fill row gap in "{}".' \ + .format(cell.getName()) + , ' (@{}, lenght:{})' \ + .format(transf,DbU.getValueString(gapWidth)) + ] )) + + def resetFeedCount ( self ): + self.count = 0 + + # ---------------------------------------------------------------------------- # Class : "configuration.IoPin". @@ -766,6 +828,7 @@ class BlockConf ( GaugeConf ): self.framework = CRL.AllianceFramework.get() self.cfg = CfgCache('',Cfg.Parameter.Priority.Interactive) self.bufferConf = BufferInterface( self.framework ) + self.feedsConf = FeedsConf( self.framework ) self.chipConf = ChipConf( self ) self.bColumns = 2 self.bRows = 2 @@ -833,6 +896,11 @@ class BlockConf ( GaugeConf ): @property def core ( self ): return self.cell + @property + def cellPnR ( self ): + if self.icorona: return self.corona + return self.cell + def setEditor ( self, editor ): self.editor = editor def refresh ( self, cell=None ): @@ -843,7 +911,7 @@ class BlockConf ( GaugeConf ): self.editor.fit() def createBuffer ( self ): - return self.bufferConf.createBuffer( self.cell ) + return self.bufferConf.createBuffer( self.cellPnR ) def setDeltaAb ( self, dx1, dy1, dx2, dy2 ): self.deltaAb = [ dx1, dy1, dx2, dy2 ] diff --git a/cumulus/src/plugins/alpha/block/spares.py b/cumulus/src/plugins/alpha/block/spares.py index cb9260d7..69c4da0b 100644 --- a/cumulus/src/plugins/alpha/block/spares.py +++ b/cumulus/src/plugins/alpha/block/spares.py @@ -144,20 +144,21 @@ class BufferPool ( object ): def _createBuffers ( self ): """Create the matrix of instances buffer.""" trace( 540, ',+', '\tBufferPool.createBuffers()\n' ) - + yoffset = 0 + if self.quadTree.spares.conf.isCoreBlock: + yoffset = self.quadTree.spares.conf.icore.getTransformation().getTy() conf = self.quadTree.spares.conf sliceHeight = conf.sliceHeight - x = self.quadTree.onXPitch( self.quadTree.area.getXCenter() - - (conf.bufferConf.width * self.columns)/2 ) - y = self.quadTree.onYSlice( self.quadTree.area.getYCenter() - - (conf.bufferConf.height * self.rows)/2 ) - slice = y / sliceHeight - + x = self.quadTree.spares.toXPitch( self.quadTree.area.getXCenter() + - (conf.bufferConf.width * self.columns)/2 ) + y = self.quadTree.spares.toYSlice( self.quadTree.area.getYCenter() + - (conf.bufferConf.height * self.rows)/2 ) + slice = (y - yoffset) / sliceHeight trace( 540, '\tSlice height: {}\n'.format(DbU.getValueString(sliceHeight)) ) - + trace( 540, '\tSlice #{} (y:{})\n'.format(slice,DbU.getValueString(y)) ) for row in range(self.rows): orientation = Transformation.Orientation.ID - y = (slice+row) * sliceHeight + y = (slice+row) * sliceHeight + yoffset if (slice+row)%2: orientation = Transformation.Orientation.MY y += sliceHeight @@ -175,10 +176,22 @@ class BufferPool ( object ): , trBufAb.getXMax(), trBufAb.getYMax() ) trace( 540, '-' ) + def _removeUnuseds ( self ): + conf = self.quadTree.spares.conf + for i in range(self.rows*self.columns): + if not (self.buffers[i][0] & Spares.USED): + trace( 540, '\tRemove Unused Buffer[{}]: {}\n'.format(i,self.buffers[i]) ) + cell = self.buffers[i][1].getCell() + transformation = self.buffers[i][1].getTransformation() + gapWidth = self.buffers[i][1].getMasterCell().getAbutmentBox().getWidth() + self.buffers[i][1].destroy() + conf.feedsConf.fillAt( cell, transformation, gapWidth ) + def _destroyBuffers ( self ): """Destroy all the buffer instances of the pool.""" for flags, buffer in self.buffers: - buffer.destroy() + if buffer is not None: + buffer.destroy() def getUse ( self ): """Return the pool occupancy, a tuple ``(occupancy,capacity)``.""" @@ -213,7 +226,11 @@ class QuadTree ( object ): @staticmethod def create ( spares ): - root = QuadTree( spares, None, spares.conf.cell.getAbutmentBox() ) + area = spares.conf.cell.getAbutmentBox() + if spares.conf.isCoreBlock: + area = spares.conf.core.getAbutmentBox() + spares.conf.icore.getTransformation().applyOn( area ) + root = QuadTree( spares, None, area ) root.rpartition() return root @@ -261,6 +278,13 @@ class QuadTree ( object ): def __eq__ ( self, other ): return self.rtag == other.rtag + def removeUnusedBuffers ( self ): + if self.bl: self.bl.removeUnusedBuffers() + if self.br: self.br.removeUnusedBuffers() + if self.tl: self.tl.removeUnusedBuffers() + if self.tr: self.tr.removeUnusedBuffers() + self.pool._removeUnuseds() + def rshowPoolUse ( self ): rused = 0 rtotal = 0 @@ -354,16 +378,6 @@ class QuadTree ( object ): """The output Plug of the currently selected buffer in the pool.""" return utils.getPlugByName( self.buffer, self.spares.conf.bufferConf.output ) - def onYSlice ( self, y ): - """Returns the coordinate of the slice immediately inferior to Y.""" - modulo = (y - self.area.getYMin()) % self.spares.conf.sliceHeight - return y - modulo - - def onXPitch ( self, x ): - """Returns the coordinate of the pitch immediately inferior to X.""" - modulo = (x - self.area.getXMin()) % self.spares.conf.sliceStep - return x - modulo - def selectFree ( self ): """ Returns the first free buffer *instance* in the pool or None if @@ -382,7 +396,7 @@ class QuadTree ( object ): trace( 540, '\tQuadTree.connectBuffer(): rtag:"{}"\n'.format(self.rtag) ) plug = self.bOutputPlug if not plug.getNet(): - outputNetBuff = Net.create( self.spares.conf.cell,'{}_{}' \ + outputNetBuff = Net.create( self.spares.conf.cellPnR,'{}_{}' \ .format(self.root.bufferTag,self.rtag) ) plug.setNet( outputNetBuff ) trace( 540, '\t| {}\n'.format(plug) ) @@ -429,7 +443,7 @@ class QuadTree ( object ): return False if aspectRatio < 0.5: - self.ycut = self.spares.toYGCellGrid( self.area.getYMin() + self.area.getHeight()/2 ) + self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 ) self.bl = QuadTree( self.spares , self , Box( self.area.getXMin() @@ -448,7 +462,7 @@ class QuadTree ( object ): trace( 540, '-' ) return True elif aspectRatio > 2.0: - self.xcut = self.spares.toXGCellGrid( self.area.getXMin() + self.area.getWidth()/2 ) + self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth()/2 ) self.bl = QuadTree( self.spares , self , Box( self.area.getXMin() @@ -467,8 +481,8 @@ class QuadTree ( object ): trace( 540, '-' ) return True - self.ycut = self.spares.toYGCellGrid( self.area.getYMin() + self.area.getHeight()/2 ) - self.xcut = self.spares.toXGCellGrid( self.area.getXMin() + self.area.getWidth ()/2 ) + self.ycut = self.spares.toYSlice( self.area.getYMin() + self.area.getHeight()/2 ) + self.xcut = self.spares.toXPitch( self.area.getXMin() + self.area.getWidth ()/2 ) self.bl = QuadTree( self.spares , self , Box( self.area.getXMin() @@ -648,6 +662,9 @@ class QuadTree ( object ): position = plugOccurrence.getBoundingBox().getCenter() self.getLeafUnder(position).plugs.append( plugOccurrence ) + def isUnderArea ( self, plugOccurrence ): + return self.area.contains( plugOccurrence.getBoundingBox().getCenter() ) + def splitNetlist ( self ): """ Reorganize the netlist by connecting all plugs to the output of the @@ -665,15 +682,15 @@ class QuadTree ( object ): 2.b. Connect the plug to the buffer output net at the same level. - No net/buffer will be used if the plug list is empty. + If the plug list is empty, the buffer will still be used and it's + output net created. """ - if not self.plugs: return - trace( 540, ',+', '\tQuadTree.spliNetlist()\n' ) self.connectBuffer( doLeaf=True ) netBuff = self.bOutputPlug.getNet() trace( 540, '\tBuffer: {}\n'.format(self.buffer) ) trace( 540, '\tBuffer output: {}\n'.format(netBuff) ) + if not self.plugs: return for plug in self.plugs: trace( 540, '\t| Leaf: {}\n'.format(plug) ) trace( 540, '\t| netBuff: {}\n'.format(netBuff) ) @@ -742,16 +759,33 @@ class Spares ( object ): if not areaLength: raise ErrorMessage( 3, 'Spares.getSpareSpaceMargin(): Spare leaf area is zero.' ) return (float(bufferLength) * 1.4) / float(areaLength) + + def toXPitch ( self, x ): + """ + Returns the coordinate of the pitch immediately inferior to X. + If we are in a chip, compute coordinate in the *corona* system. + """ + offset = 0 + area = self.conf.coreAb + if self.conf.isCoreBlock: + offset = self.conf.icore.getTransformation().getTx() + self.conf.icore.getTransformation().applyOn( area ) + modulo = (x - offset - area.getXMin()) % self.conf.sliceStep + return x - modulo - def toXGCellGrid ( self, x ): - """Find the nearest X (inferior) on the Cell gauge grid (sliceStep).""" - dx = x - self.conf.xMin - return self.conf.xMin + (dx - dx % self.conf.sliceStep) - - def toYGCellGrid ( self, y ): - """Find the nearest Y (inferior) on the Cell gauge grid (sliceHeight).""" - dy = y - self.conf.yMin - return self.conf.yMin + (dy - dy % self.conf.sliceHeight) + def toYSlice ( self, y ): + """ + Returns the coordinate of the slice immediately inferior to Y. + If we are in a chip, compute coordinate in the *corona* system. + """ + offset = 0 + area = self.conf.coreAb + if self.conf.isCoreBlock: + offset = self.conf.icore.getTransformation().getTy() + self.conf.icore.getTransformation().applyOn( area ) + trace( 540, '\toffset:\n'.format(DbU.getValueString(offset)) ) + modulo = (y - offset - area.getYMin()) % self.conf.sliceHeight + return y - modulo def build ( self ): if not self.conf.useSpares: return @@ -773,8 +807,8 @@ class Spares ( object ): trace( 540, ',+', '\tSpares.addStrayBuffer()\n' ) sliceHeight = self.conf.sliceHeight - x = self.quadTree.onXPitch( position.getX() ) - y = self.quadTree.onYSlice( position.getY() ) + x = self.quadTree.toXPitch( position.getX() ) + y = self.quadTree.toYSlice( position.getY() ) slice = y / sliceHeight orientation = Transformation.Orientation.ID y = slice * sliceHeight @@ -845,6 +879,7 @@ class Spares ( object ): *plug master net* and the *tail path*. """ + trace( 540, '\tSpares.raddTransNet() top:{} path:{}\n'.format(topNet,path) ) if path.isEmpty(): self.addClonedCell( topNet.getCell() ) return None @@ -853,6 +888,7 @@ class Spares ( object ): headPlug = utils.getPlugByNet(headInstance,topNet) if not headPlug: masterCell = headInstance.getMasterCell() + trace( 540, '\tcreate Plug in {}\n'.format(headInstance) ) masterNet = Net.create( masterCell, topNet.getName() ) masterNet.setExternal ( True ) masterNet.setType ( topNet.getType() ) @@ -866,9 +902,14 @@ class Spares ( object ): self.addClonedCell( headInstance.getCell() ) else: masterNet = headPlug.getMasterNet() + trace( 540, '\ttailPath {}\n'.format(tailPath) ) if tailPath.isEmpty(): return headPlug return self.raddTransNet( masterNet, tailPath ) + def removeUnusedBuffers ( self ): + with UpdateSession(): + self.quadTree.removeUnusedBuffers() + def rsave ( self, cell ): """ Save the complete cell hierarchy. Saves only the physical view, except @@ -896,5 +937,7 @@ class Spares ( object ): for cell in self.cloneds: trace( 550, '\tRenaming cloned cell: "{}"\n'.format(cell) ) cell.setName( cell.getName()+'_cts' ) + if self.conf.chip is None: + self.conf.cell.setName( self.conf.cell.getName()+'_r' ) self.rsave( self.conf.cell ) return diff --git a/cumulus/src/plugins/alpha/chip/chip.py b/cumulus/src/plugins/alpha/chip/chip.py index 120f380d..bcc45a70 100644 --- a/cumulus/src/plugins/alpha/chip/chip.py +++ b/cumulus/src/plugins/alpha/chip/chip.py @@ -148,6 +148,8 @@ class Chip ( Block ): if not self.conf.validated: raise ErrorMessage( 1, 'chip.save(): Chip is not valid, aborting.' ) super(Chip,self).save() + self.conf.corona.setName( self.conf.corona.getName()+'_r' ) + self.conf.chip .setName( self.conf.chip .getName()+'_r' ) af = CRL.AllianceFramework.get() af.saveCell( self.conf.corona, CRL.Catalog.State.Views ) af.saveCell( self.conf.chip , CRL.Catalog.State.Views ) diff --git a/cumulus/src/plugins/alpha/chip/configuration.py b/cumulus/src/plugins/alpha/chip/configuration.py index 43c8d0d6..4496545c 100644 --- a/cumulus/src/plugins/alpha/chip/configuration.py +++ b/cumulus/src/plugins/alpha/chip/configuration.py @@ -158,7 +158,7 @@ class ChipConf ( BlockConf ): #self.checkPads() #self.checkCorona() #self.computeChipSize() - #self.checkChipSize() + self.checkChipSize() self.findPowerAndClockNets() return @@ -577,6 +577,22 @@ class ChipConf ( BlockConf ): return def checkChipSize ( self ): + print( 'checkChipSize' ) + if self.chipSize[0] % self.sliceStep: + print( WarningMessage( 'ChipConf.checkChipSize(): Width of "{}" ({})is not on sliceStep ({}), ajusted.' \ + .format( self.chipConf.name + , DbU.getValueString(self.chipSize[0]) + , DbU.getValueString(self.sliceStep))) ) + adjust = self.sliceStep - self.chipSize[0] % self.sliceStep + self.chipSize = (self.chipSize[0] + adjust, self.chipSize[1]) + if self.chipSize[1] % self.sliceStep: + print( WarningMessage( 'ChipConf.checkChipSize(): Height of "{}" ({})is not on sliceStep ({}), ajusted.' \ + .format( self.chipConf.name + , DbU.getValueString(self.chipSize[1]) + , DbU.getValueString(self.sliceStep))) ) + adjust = self.sliceStep - self.chipSize[1] % self.sliceStep + self.chipSize = (self.chipSize[0], self.chipSize[1] + adjust) + #if self._coreSize.isEmpty(): return # #minWidth = self._coreSize.getWidth () + self._minCorona + 2*self._padHeight diff --git a/cumulus/src/plugins/alpha/chip/corona.py b/cumulus/src/plugins/alpha/chip/corona.py index f1fc2f61..b439142a 100644 --- a/cumulus/src/plugins/alpha/chip/corona.py +++ b/cumulus/src/plugins/alpha/chip/corona.py @@ -488,6 +488,8 @@ class Builder ( object ): def __init__ ( self, block ): self.block = block self.innerBb = self.block.bb + print( 'Builder.__init__(): innerBb: {}'.format(self.innerBb) ) + print( self.block.path.getTransformation()) self.block.path.getTransformation().applyOn( self.innerBb ) self.innerBb.inflate( self.hRailSpace/2, self.vRailSpace/2 ) self.southSide = SouthSide( self ) diff --git a/cumulus/src/plugins/alpha/chip/power.py b/cumulus/src/plugins/alpha/chip/power.py index 90457839..22aa4b37 100644 --- a/cumulus/src/plugins/alpha/chip/power.py +++ b/cumulus/src/plugins/alpha/chip/power.py @@ -180,7 +180,7 @@ class Builder ( object ): def __init__ ( self, conf ): self.conf = conf self.path = Path( self.conf.icore ) - self.block = self.path.getTailInstance().getMasterCell() + self.block = self.conf.icore.getMasterCell() self.bb = self.block.getAbutmentBox() self.planes = {} self.activePlane = None @@ -211,27 +211,30 @@ class Builder ( object ): raise ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' ) return blockCk = None - for plug in self.path.getTailInstance().getPlugs(): + for plug in self.conf.icore.getPlugs(): if plug.getNet() == self.conf.coronaCk: blockCk = plug.getMasterNet() if not blockCk: raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \ - .format(self.path.getTailInstance().getName(),self.ck.getName()) ) + .format(self.conf.icore.getName(),self.conf.coronaCk.getName()) ) return htPlugs = [] - ffPlugs = [] - for plug in blockCk.getPlugs(): - if not plug.getInstance().isTerminalNetlist(): continue - htPlugs.append( plug ) + for plug in self.conf.coronaCk.getPlugs(): + print( plug ) + if plug.getInstance().isTerminalNetlist(): + htPlugs.append( plug ) if len(htPlugs) != 1: - message = 'Clock "{}" of block "{}" is not organized as a H-Tree.' \ - .format(blockCk.getName(),self.path.getTailInstance().getName()) + message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \ + .format( self.conf.coronaCk.getName() + , self.conf.icore.getName() + , len(htPlugs)) ] + print( self.conf.icore ) for plug in htPlugs: - message += '\n - {}'.format(plug) + message += [ '\n - {} {}'.format(plug,plug.getInstance()) ] raise ErrorMessage( 1, message ) return with UpdateSession(): - bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], self.path) + bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()) , self.conf.coronaCk , 0 ) blockAb = self.block.getAbutmentBox() diff --git a/cumulus/src/plugins/alpha/core2chip/core2chip.py b/cumulus/src/plugins/alpha/core2chip/core2chip.py index 7d818736..891c81ea 100644 --- a/cumulus/src/plugins/alpha/core2chip/core2chip.py +++ b/cumulus/src/plugins/alpha/core2chip/core2chip.py @@ -248,8 +248,8 @@ class IoPad ( object ): @property def pads ( self ): - print( self.ioPadConf ) - return self.ioPadConf.pads + print( self.ioPadConf ) + return self.ioPadConf.pads def __str__ ( self ): s = '