Add management of fixed wires to Kite (for chip ClockTree)
* Change: In Hurricane, in Plug::setNet(), more informative error messages. * Change: In Hurricane, In Segment, more informative error messages. * Change: In Hurricane, In DeepNet, accessor for the Net occurrence. * Bug: In Katabatic, in AutoSegment::create(), error message uses correct variables (vertical was using horizontal)... * Change: In Kite, in BuildPowerRails, already existing wiring in instances is copied up as blockage. Uses blockage layer instead of true layer (it was a bug). * Change: In Kite, in BuildPreRouted, consider as manual global routing nets with only default wiring (default size wire & contacts). Non-default routing is flagged as fixed (with the NetRoutingState property).
This commit is contained in:
parent
fb4a7457a1
commit
51a3236962
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
link_directories ( ${CRLCORE_BINARY_DIR}/src/ccore )
|
link_directories ( ${CRLCORE_BINARY_DIR}/src/ccore )
|
||||||
|
|
||||||
|
# add_executable ( cyclop ${cpps} )
|
||||||
add_executable ( cyclop ${cpps} ${mocCpps} )
|
add_executable ( cyclop ${cpps} ${mocCpps} )
|
||||||
target_link_libraries ( cyclop crlcore
|
target_link_libraries ( cyclop crlcore
|
||||||
${HURRICANE_PYTHON_LIBRARIES}
|
${HURRICANE_PYTHON_LIBRARIES}
|
||||||
|
|
|
@ -1,582 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
|
||||||
# This file is part of the Coriolis Software.
|
|
||||||
# Copyright (c) UPMC 2014-2014, All Rights Reserved
|
|
||||||
#
|
|
||||||
# +-----------------------------------------------------------------+
|
|
||||||
# | C O R I O L I S |
|
|
||||||
# | C u m u l u s - P y t h o n T o o l s |
|
|
||||||
# | |
|
|
||||||
# | Author : Jean-Paul CHAPUT |
|
|
||||||
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
||||||
# | =============================================================== |
|
|
||||||
# | Python : "./plugins/ClockTree.cpp" |
|
|
||||||
# +-----------------------------------------------------------------+
|
|
||||||
|
|
||||||
try:
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
import os.path
|
|
||||||
import optparse
|
|
||||||
import math
|
|
||||||
import Cfg
|
|
||||||
import Hurricane
|
|
||||||
from Hurricane import DbU
|
|
||||||
from Hurricane import Transformation
|
|
||||||
from Hurricane import Box
|
|
||||||
from Hurricane import Path
|
|
||||||
from Hurricane import Occurrence
|
|
||||||
from Hurricane import UpdateSession
|
|
||||||
from Hurricane import Breakpoint
|
|
||||||
from Hurricane import Net
|
|
||||||
from Hurricane import RoutingPad
|
|
||||||
from Hurricane import Contact
|
|
||||||
from Hurricane import Horizontal
|
|
||||||
from Hurricane import Vertical
|
|
||||||
from Hurricane import Instance
|
|
||||||
from Hurricane import HyperNet
|
|
||||||
import Viewer
|
|
||||||
import CRL
|
|
||||||
from CRL import RoutingLayerGauge
|
|
||||||
from helpers import ErrorMessage
|
|
||||||
import Nimbus
|
|
||||||
import Metis
|
|
||||||
import Mauka
|
|
||||||
import Katabatic
|
|
||||||
import Kite
|
|
||||||
import Unicorn
|
|
||||||
import plugins
|
|
||||||
except ImportError, e:
|
|
||||||
module = str(e).split()[-1]
|
|
||||||
|
|
||||||
print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module
|
|
||||||
print ' Please check the integrity of the <coriolis> package.'
|
|
||||||
sys.exit(1)
|
|
||||||
except Exception, e:
|
|
||||||
print '[ERROR] A strange exception occurred while loading the basic Coriolis/Python'
|
|
||||||
print ' modules. Something may be wrong at Python/C API level.\n'
|
|
||||||
print ' %s' % e
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
|
|
||||||
# Will be moved away from the students eyes in the future.
|
|
||||||
def breakpoint ( editor, level, message ):
|
|
||||||
if editor:
|
|
||||||
editor.fit()
|
|
||||||
editor.refresh()
|
|
||||||
Breakpoint.stop( level, message )
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def getPlugByName ( instance, netName ):
|
|
||||||
masterCell = instance.getMasterCell()
|
|
||||||
masterNet = masterCell.getNet( netName )
|
|
||||||
if masterNet:
|
|
||||||
return instance.getPlug( masterNet )
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def getPlugByNet ( instance, net ):
|
|
||||||
#print 'getPlugByNet:', net, 'connected to', instance
|
|
||||||
for plug in net.getPlugs():
|
|
||||||
#print '|', plug
|
|
||||||
if plug.getInstance() == instance:
|
|
||||||
#print '| Found.'
|
|
||||||
return plug
|
|
||||||
#print '| NOT Found'
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def showNet ( cell, netName ):
|
|
||||||
net = cell.getNet(netName)
|
|
||||||
if not net:
|
|
||||||
print ErrorMessage( 3, 'Cell %s doesn\'t have net %s' % cell.getName(), netName )
|
|
||||||
return
|
|
||||||
|
|
||||||
print 'Components of', netName
|
|
||||||
for component in net.getComponents():
|
|
||||||
print '| ', component, component.getBoundingBox()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class HTree ( object ):
|
|
||||||
|
|
||||||
HAccess = 0x0001
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def create ( cell, clockBox ):
|
|
||||||
if clockBox.isEmpty(): raise ErrorMessage( 3, 'ClockTree: The clock area is empty.' )
|
|
||||||
|
|
||||||
aspectRatio = DbU.toLambda( clockBox.getWidth() ) / DbU.toLambda( clockBox.getHeight() )
|
|
||||||
if aspectRatio > 1.5 or aspectRatio < 0.5:
|
|
||||||
raise ErrorMessage( 3, 'ClockTree: aspect ratio %f is disproportionate, must be between 0.5 and 1.5.' \
|
|
||||||
% aspectRatio )
|
|
||||||
|
|
||||||
ht = HTree( cell, clockBox )
|
|
||||||
print ' o Creating Clock H-Tree for <%s>.' % cell.getName()
|
|
||||||
ht.build()
|
|
||||||
ht.place()
|
|
||||||
ht.route()
|
|
||||||
print ' - H-Tree depth: %d' % ht.getTreeDepth()
|
|
||||||
return ht
|
|
||||||
|
|
||||||
def __init__ ( self, cell, area ):
|
|
||||||
self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt() )
|
|
||||||
if self.minSide < DbU.fromLambda(100.0):
|
|
||||||
raise ErrorMessage( 3, 'ClockTree: clockTree.minimumSide (%g) is less than 100 lambda.' \
|
|
||||||
% DbU.toLambda(self.minSide) )
|
|
||||||
|
|
||||||
self.framework = CRL.AllianceFramework.get()
|
|
||||||
self.cell = cell
|
|
||||||
self.area = area
|
|
||||||
self.childs = []
|
|
||||||
self.bufferCell = self.framework.getCell( 'buf_x2', CRL.Catalog.State.Logical )
|
|
||||||
self.cellGauge = self.framework.getCellGauge()
|
|
||||||
self.routingGauge = self.framework.getRoutingGauge()
|
|
||||||
self.topBuffer = Instance.create( self.cell, 'ck_htree', self.bufferCell )
|
|
||||||
self.cloneds = [ self.cell ]
|
|
||||||
self.plugToRp = {}
|
|
||||||
self._createChildNet( self.topBuffer, 'ck_htree' )
|
|
||||||
|
|
||||||
topLayer = Cfg.getParamString('katabatic.topRoutingLayer').asString()
|
|
||||||
self.topLayerDepth = 0
|
|
||||||
for layerGauge in self.routingGauge.getLayerGauges():
|
|
||||||
if layerGauge.getLayer().getName() == topLayer:
|
|
||||||
self.topLayerDepth = layerGauge.getDepth()
|
|
||||||
break
|
|
||||||
if not self.topLayerDepth:
|
|
||||||
print '[WARNING] Gauge top layer not defined, using top of gauge (%d).' \
|
|
||||||
% self.routingGauge.getDepth()
|
|
||||||
self.topLayerDepth = self.routingGauge.getDepth()
|
|
||||||
|
|
||||||
self.horizontalDepth = 0
|
|
||||||
self.verticalDepth = 0
|
|
||||||
for depth in range(0,self.topLayerDepth+1):
|
|
||||||
if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal:
|
|
||||||
self.horizontalDepth = depth
|
|
||||||
if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical:
|
|
||||||
self.verticalDepth = depth
|
|
||||||
|
|
||||||
self.masterClock = None
|
|
||||||
for net in cell.getNets():
|
|
||||||
if net.isClock():
|
|
||||||
self.masterClock = net
|
|
||||||
break
|
|
||||||
if not self.masterClock:
|
|
||||||
print '[WARNING] Cell %s has no clock net.' % cell.getName()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def _createChildNet ( self, ibuffer, tag ):
|
|
||||||
childNet = Net.create( self.cell, tag )
|
|
||||||
childNet.setType( Net.Type.CLOCK )
|
|
||||||
getPlugByName(ibuffer, 'q').setNet( childNet )
|
|
||||||
return
|
|
||||||
|
|
||||||
def _createContact ( self, net, x, y ):
|
|
||||||
return Contact.create( net
|
|
||||||
, self.routingGauge.getContactLayer(self.horizontalDepth)
|
|
||||||
, x, y
|
|
||||||
, self.routingGauge.getLayerGauge(self.horizontalDepth).getViaWidth()
|
|
||||||
, self.routingGauge.getLayerGauge(self.horizontalDepth).getViaWidth()
|
|
||||||
)
|
|
||||||
|
|
||||||
def _createHorizontal ( self, source, target, y ):
|
|
||||||
return Horizontal.create( source
|
|
||||||
, target
|
|
||||||
, self.routingGauge.getRoutingLayer(self.horizontalDepth)
|
|
||||||
, y
|
|
||||||
, self.routingGauge.getLayerGauge(self.horizontalDepth).getWireWidth()
|
|
||||||
)
|
|
||||||
|
|
||||||
def _createVertical ( self, source, target, x ):
|
|
||||||
return Vertical.create( source
|
|
||||||
, target
|
|
||||||
, self.routingGauge.getRoutingLayer(self.verticalDepth)
|
|
||||||
, x
|
|
||||||
, self.routingGauge.getLayerGauge(self.verticalDepth).getWireWidth()
|
|
||||||
)
|
|
||||||
|
|
||||||
def _rpAccess ( self, rp, net, flags=0 ):
|
|
||||||
contact1 = Contact.create( rp, self.routingGauge.getContactLayer(0), 0, 0 )
|
|
||||||
|
|
||||||
if flags & HTree.HAccess: stopDepth = self.horizontalDepth
|
|
||||||
else: stopDepth = self.verticalDepth
|
|
||||||
|
|
||||||
for depth in range(1,stopDepth):
|
|
||||||
contact2 = Contact.create( net
|
|
||||||
, self.routingGauge.getContactLayer(depth)
|
|
||||||
, contact1.getX()
|
|
||||||
, contact1.getY()
|
|
||||||
, self.routingGauge.getLayerGauge(depth).getViaWidth()
|
|
||||||
, self.routingGauge.getLayerGauge(depth).getViaWidth()
|
|
||||||
)
|
|
||||||
if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal:
|
|
||||||
Horizontal.create( contact1
|
|
||||||
, contact2
|
|
||||||
, self.routingGauge.getRoutingLayer(depth)
|
|
||||||
, contact1.getY()
|
|
||||||
, self.routingGauge.getLayerGauge(depth).getWireWidth()
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
Vertical.create( contact1
|
|
||||||
, contact2
|
|
||||||
, self.routingGauge.getRoutingLayer(depth)
|
|
||||||
, contact1.getX()
|
|
||||||
, self.routingGauge.getLayerGauge(depth).getWireWidth()
|
|
||||||
)
|
|
||||||
contact1 = contact2
|
|
||||||
|
|
||||||
return contact1
|
|
||||||
|
|
||||||
def _rpAccessByOccurrence ( self, occurrence, net, flags=0 ):
|
|
||||||
plug = occurrence.getEntity()
|
|
||||||
if self.plugToRp.has_key(plug):
|
|
||||||
rp = self.plugToRp[plug]
|
|
||||||
else:
|
|
||||||
rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea )
|
|
||||||
self.plugToRp[plug] = rp
|
|
||||||
|
|
||||||
return self._rpAccess( rp, net, flags )
|
|
||||||
|
|
||||||
def _rpAccessByPlug ( self, plug, net, flags=0 ):
|
|
||||||
if self.plugToRp.has_key(plug):
|
|
||||||
rp = self.plugToRp[plug]
|
|
||||||
else:
|
|
||||||
occurrence = Occurrence( plug, Path(self.cell,'') )
|
|
||||||
rp = RoutingPad.create( net, occurrence, RoutingPad.BiggestArea )
|
|
||||||
self.plugToRp[plug] = rp
|
|
||||||
|
|
||||||
return self._rpAccess( rp, net, flags )
|
|
||||||
|
|
||||||
def _rpAccessByPlugName ( self, instance, plugName, net, flags=0 ):
|
|
||||||
return self._rpAccessByPlug( getPlugByName(instance,plugName), net, flags )
|
|
||||||
|
|
||||||
def toXCellGrid ( self, x ): return x - (x % self.cellGauge.getSliceStep ())
|
|
||||||
def toYCellGrid ( self, y ): return y - (y % self.cellGauge.getSliceHeight())
|
|
||||||
|
|
||||||
def placeInstance ( self, instance, x, y ):
|
|
||||||
xslice = self.toXCellGrid(x)
|
|
||||||
yslice = self.toYCellGrid(y)
|
|
||||||
|
|
||||||
transformation = Transformation.Orientation.ID
|
|
||||||
if (yslice / self.cellGauge.getSliceHeight()) % 2 != 0:
|
|
||||||
transformation = Transformation.Orientation.MY
|
|
||||||
yslice += self.cellGauge.getSliceHeight()
|
|
||||||
|
|
||||||
instance.setTransformation ( Transformation(xslice, yslice, transformation) )
|
|
||||||
instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
|
|
||||||
return
|
|
||||||
|
|
||||||
def getTreeDepth ( self ):
|
|
||||||
return self.childs[0].getTreeDepth()
|
|
||||||
|
|
||||||
def getLeafBufferUnder ( self, point ):
|
|
||||||
return self.childs[0].getLeafBufferUnder( point )
|
|
||||||
|
|
||||||
def build ( self ):
|
|
||||||
self.childs.append( HTreeNode( self, self.topBuffer, self.area, '', HTreeNode.RootBranch ) )
|
|
||||||
return
|
|
||||||
|
|
||||||
def place ( self ):
|
|
||||||
UpdateSession.open()
|
|
||||||
center = self.area.getCenter()
|
|
||||||
self.placeInstance( self.topBuffer, center.getX(), center.getY() )
|
|
||||||
self.childs[0].place()
|
|
||||||
UpdateSession.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
def route ( self ):
|
|
||||||
UpdateSession.open()
|
|
||||||
self.childs[0].route()
|
|
||||||
UpdateSession.close()
|
|
||||||
return
|
|
||||||
|
|
||||||
def addDeepPlug ( self, topNet, path ):
|
|
||||||
if path.isEmpty(): return None
|
|
||||||
|
|
||||||
tailPath = path.getTailPath()
|
|
||||||
headInstance = path.getHeadInstance()
|
|
||||||
headPlug = getPlugByNet(headInstance,topNet)
|
|
||||||
if headPlug:
|
|
||||||
if tailPath.isEmpty(): return headPlug
|
|
||||||
return self.addDeepPlug( headPlug.getMasterNet(), tailPath )
|
|
||||||
|
|
||||||
masterCell = headInstance.getMasterCell()
|
|
||||||
masterNet = Net.create( masterCell, topNet.getName() )
|
|
||||||
masterNet.setExternal ( True )
|
|
||||||
masterNet.setType ( Net.Type.CLOCK )
|
|
||||||
masterNet.setDirection( Net.Direction.IN )
|
|
||||||
headPlug = headInstance.getPlug( masterNet )
|
|
||||||
if not headPlug:
|
|
||||||
raise ErrorMessage( 3, 'Plug not created for %s on instance %s of %s' \
|
|
||||||
% (topNet.getName(),headInstance.getName(),masterCell.getName()) )
|
|
||||||
headPlug.setNet( topNet )
|
|
||||||
if not masterCell in self.cloneds: self.cloneds.append( masterCell )
|
|
||||||
|
|
||||||
if tailPath.isEmpty(): return headPlug
|
|
||||||
return self.addDeepPlug( masterNet, tailPath )
|
|
||||||
|
|
||||||
def connectLeaf ( self ):
|
|
||||||
UpdateSession.open()
|
|
||||||
|
|
||||||
leafConnects = []
|
|
||||||
hyperMasterClock = HyperNet.create( Occurrence(self.masterClock) )
|
|
||||||
for plugOccurrence in hyperMasterClock.getLeafPlugOccurrences():
|
|
||||||
position = plugOccurrence.getBoundingBox().getCenter()
|
|
||||||
leafBuffer = self.getLeafBufferUnder( position )
|
|
||||||
leafCk = getPlugByName(leafBuffer,'q').getNet()
|
|
||||||
deepPlug = self.addDeepPlug( leafCk, plugOccurrence.getPath() )
|
|
||||||
leafConnects.append( (deepPlug,plugOccurrence,leafCk,leafBuffer) )
|
|
||||||
|
|
||||||
for deepPlug, plugOccurrence, leafCk, leafBuffer in leafConnects:
|
|
||||||
plugOccurrence.getEntity().setNet( deepPlug.getMasterNet() )
|
|
||||||
|
|
||||||
bufferContact = self._rpAccessByPlugName( leafBuffer, 'q', leafCk , HTree.HAccess )
|
|
||||||
registerContact = self._rpAccessByOccurrence( plugOccurrence, leafCk, 0 )
|
|
||||||
turn = self._createContact( leafCk, registerContact.getX(), bufferContact.getY() )
|
|
||||||
self._createVertical ( registerContact, turn, registerContact.getX() )
|
|
||||||
self._createHorizontal( turn, bufferContact, bufferContact.getY() )
|
|
||||||
|
|
||||||
getPlugByName( self.topBuffer, 'i' ).setNet( self.masterClock )
|
|
||||||
UpdateSession.close()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def _rsave ( self, cell ):
|
|
||||||
flags = CRL.Catalog.State.Physical
|
|
||||||
if cell.getName().endswith('_clocked'):
|
|
||||||
flags = flags | CRL.Catalog.State.Logical
|
|
||||||
self.framework.saveCell( cell, flags )
|
|
||||||
|
|
||||||
for instance in cell.getInstances():
|
|
||||||
masterCell = instance.getMasterCell()
|
|
||||||
if not masterCell.isTerminal():
|
|
||||||
self._rsave( masterCell )
|
|
||||||
|
|
||||||
def save ( self ):
|
|
||||||
for cell in self.cloneds:
|
|
||||||
cell.setName( cell.getName()+'_clocked' )
|
|
||||||
|
|
||||||
self._rsave( self.cell )
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
class HTreeNode ( object ):
|
|
||||||
|
|
||||||
RootBranch = 0x0001
|
|
||||||
LeftBranch = 0x0002
|
|
||||||
RightBranch = 0x0004
|
|
||||||
UpBranch = 0x0008
|
|
||||||
DownBranch = 0x0010
|
|
||||||
|
|
||||||
def __init__ ( self, topTree, sourceBuffer, area, prefix, flags ):
|
|
||||||
self.topTree = topTree
|
|
||||||
self.childs = []
|
|
||||||
self.flags = flags
|
|
||||||
self.sourceBuffer = sourceBuffer
|
|
||||||
self.area = area
|
|
||||||
self.prefix = prefix
|
|
||||||
|
|
||||||
self.blBuffer = Instance.create( self.topTree.cell, 'ck_htree'+self.prefix+'_bl_ins', self.topTree.bufferCell )
|
|
||||||
self.brBuffer = Instance.create( self.topTree.cell, 'ck_htree'+self.prefix+'_br_ins', self.topTree.bufferCell )
|
|
||||||
self.tlBuffer = Instance.create( self.topTree.cell, 'ck_htree'+self.prefix+'_tl_ins', self.topTree.bufferCell )
|
|
||||||
self.trBuffer = Instance.create( self.topTree.cell, 'ck_htree'+self.prefix+'_tr_ins', self.topTree.bufferCell )
|
|
||||||
self.ckNet = getPlugByName(self.sourceBuffer, 'q').getNet()
|
|
||||||
getPlugByName(self.blBuffer, 'i').setNet( self.ckNet )
|
|
||||||
getPlugByName(self.brBuffer, 'i').setNet( self.ckNet )
|
|
||||||
getPlugByName(self.tlBuffer, 'i').setNet( self.ckNet )
|
|
||||||
getPlugByName(self.trBuffer, 'i').setNet( self.ckNet )
|
|
||||||
|
|
||||||
self.topTree._createChildNet( self.blBuffer, 'ck_htree'+self.prefix+'_bl' )
|
|
||||||
self.topTree._createChildNet( self.brBuffer, 'ck_htree'+self.prefix+'_br' )
|
|
||||||
self.topTree._createChildNet( self.tlBuffer, 'ck_htree'+self.prefix+'_tl' )
|
|
||||||
self.topTree._createChildNet( self.trBuffer, 'ck_htree'+self.prefix+'_tr' )
|
|
||||||
|
|
||||||
halfWidth = self.area.getHalfWidth ()
|
|
||||||
halfHeight = self.area.getHalfHeight()
|
|
||||||
if halfWidth >= self.topTree.minSide and halfHeight >= self.topTree.minSide:
|
|
||||||
# Recursive call.
|
|
||||||
self.childs.append( HTreeNode( self.topTree, self.blBuffer, self.blArea(), self.prefix+'_bl', 0 ) )
|
|
||||||
self.childs.append( HTreeNode( self.topTree, self.brBuffer, self.brArea(), self.prefix+'_br', 0 ) )
|
|
||||||
self.childs.append( HTreeNode( self.topTree, self.tlBuffer, self.tlArea(), self.prefix+'_tl', 0 ) )
|
|
||||||
self.childs.append( HTreeNode( self.topTree, self.trBuffer, self.trArea(), self.prefix+'_tr', 0 ) )
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def xmin ( self ): return self.area.getXMin()
|
|
||||||
def xmax ( self ): return self.area.getXMax()
|
|
||||||
def ymin ( self ): return self.area.getYMin()
|
|
||||||
def ymax ( self ): return self.area.getYMax()
|
|
||||||
def halfWidth ( self ): return self.area.getHalfWidth()
|
|
||||||
def halfHeight( self ): return self.area.getHalfHeight()
|
|
||||||
|
|
||||||
def blArea ( self ):
|
|
||||||
return Box( self.xmin() , self.ymin()
|
|
||||||
, self.xmin()+self.halfWidth(), self.ymin()+self.halfHeight() )
|
|
||||||
|
|
||||||
def brArea ( self ):
|
|
||||||
return Box( self.xmin()+self.halfWidth(), self.ymin()
|
|
||||||
, self.xmax() , self.ymin()+self.halfHeight() )
|
|
||||||
|
|
||||||
def tlArea ( self ):
|
|
||||||
return Box( self.xmin() , self.ymin()+self.halfHeight()
|
|
||||||
, self.xmin()+self.halfWidth(), self.ymax() )
|
|
||||||
|
|
||||||
def trArea ( self ):
|
|
||||||
return Box( self.xmin()+self.halfWidth(), self.ymin()+self.halfHeight()
|
|
||||||
, self.xmax() , self.ymax() )
|
|
||||||
|
|
||||||
def getTreeDepth ( self ):
|
|
||||||
if self.childs: return self.childs[0].getTreeDepth()+1
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def getLeafBufferUnder ( self, point ):
|
|
||||||
if self.childs:
|
|
||||||
if self.blArea().contains(point): return self.childs[0].getLeafBufferUnder(point)
|
|
||||||
if self.brArea().contains(point): return self.childs[1].getLeafBufferUnder(point)
|
|
||||||
if self.tlArea().contains(point): return self.childs[2].getLeafBufferUnder(point)
|
|
||||||
if self.trArea().contains(point): return self.childs[3].getLeafBufferUnder(point)
|
|
||||||
|
|
||||||
if self.blArea().contains(point): return self.blBuffer
|
|
||||||
if self.brArea().contains(point): return self.brBuffer
|
|
||||||
if self.tlArea().contains(point): return self.tlBuffer
|
|
||||||
return self.trBuffer
|
|
||||||
|
|
||||||
def place ( self ):
|
|
||||||
x = self.area.getXMin() + self.area.getWidth ()/4
|
|
||||||
y = self.area.getYMin() + self.area.getHeight()/4
|
|
||||||
halfWidth = self.area.getHalfWidth ()
|
|
||||||
halfHeight = self.area.getHalfHeight()
|
|
||||||
|
|
||||||
self.topTree.placeInstance( self.blBuffer, x , y )
|
|
||||||
self.topTree.placeInstance( self.brBuffer, x+halfWidth, y )
|
|
||||||
self.topTree.placeInstance( self.tlBuffer, x , y+halfHeight )
|
|
||||||
self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight )
|
|
||||||
|
|
||||||
for child in self.childs: child.place()
|
|
||||||
return
|
|
||||||
|
|
||||||
def route ( self ):
|
|
||||||
leftSourceContact = self.topTree._rpAccessByPlugName( self.sourceBuffer, 'q', self.ckNet , HTree.HAccess )
|
|
||||||
rightSourceContact = self.topTree._rpAccessByPlugName( self.sourceBuffer, 'q', self.ckNet , HTree.HAccess )
|
|
||||||
blContact = self.topTree._rpAccessByPlugName( self.blBuffer , 'i', self.ckNet )
|
|
||||||
brContact = self.topTree._rpAccessByPlugName( self.brBuffer , 'i', self.ckNet )
|
|
||||||
tlContact = self.topTree._rpAccessByPlugName( self.tlBuffer , 'i', self.ckNet )
|
|
||||||
trContact = self.topTree._rpAccessByPlugName( self.trBuffer , 'i', self.ckNet )
|
|
||||||
leftContact = self.topTree._createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() )
|
|
||||||
rightContact = self.topTree._createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() )
|
|
||||||
self.topTree._createHorizontal( leftContact , leftSourceContact, leftSourceContact.getY() )
|
|
||||||
self.topTree._createHorizontal( rightSourceContact, rightContact , rightSourceContact.getY() )
|
|
||||||
self.topTree._createVertical ( leftContact , blContact , leftContact.getX() )
|
|
||||||
self.topTree._createVertical ( tlContact , leftContact , leftContact.getX() )
|
|
||||||
self.topTree._createVertical ( rightContact , brContact , rightContact.getX() )
|
|
||||||
self.topTree._createVertical ( trContact , rightContact , rightContact.getX() )
|
|
||||||
|
|
||||||
for child in self.childs: child.route()
|
|
||||||
return
|
|
||||||
|
|
||||||
def computeAbutmentBox ( cell, spaceMargin, aspectRatio, cellGauge ):
|
|
||||||
sliceHeight = DbU.toLambda( cellGauge.getSliceHeight() )
|
|
||||||
|
|
||||||
instancesNb = 0
|
|
||||||
cellLength = 0
|
|
||||||
for occurrence in cell.getLeafInstanceOccurrences():
|
|
||||||
instance = occurrence.getEntity()
|
|
||||||
instancesNb += 1
|
|
||||||
cellLength += int( DbU.toLambda(instance.getMasterCell().getAbutmentBox().getWidth()) )
|
|
||||||
|
|
||||||
# ar = x/y S = x*y = spaceMargin*SH x=S/y ar = S/y^2
|
|
||||||
# y = sqrt(S/AR)
|
|
||||||
gcellLength = float(cellLength)*(1+spaceMargin) / sliceHeight
|
|
||||||
rows = math.sqrt( gcellLength/aspectRatio )
|
|
||||||
if math.trunc(rows) != rows: rows = math.trunc(rows) + 1
|
|
||||||
else: rows = math.trunc(rows)
|
|
||||||
columns = gcellLength / rows
|
|
||||||
if math.trunc(columns) != columns: columns = math.trunc(columns) + 1
|
|
||||||
else: columns = math.trunc(columns)
|
|
||||||
|
|
||||||
print ' o Creating abutment box (margin:%.1f%%, aspect ratio:%.1f%%, g-length:%.1fl)' \
|
|
||||||
% (spaceMargin*100.0,aspectRatio*100.0,(cellLength/sliceHeight))
|
|
||||||
print ' - GCell grid: [%dx%d]' % (columns,rows)
|
|
||||||
|
|
||||||
UpdateSession.open()
|
|
||||||
abutmentBox = Box( DbU.fromLambda(0)
|
|
||||||
, DbU.fromLambda(0)
|
|
||||||
, DbU.fromLambda(columns*sliceHeight)
|
|
||||||
, DbU.fromLambda(rows *sliceHeight)
|
|
||||||
)
|
|
||||||
cell.setAbutmentBox( abutmentBox )
|
|
||||||
UpdateSession.close()
|
|
||||||
|
|
||||||
return abutmentBox
|
|
||||||
|
|
||||||
|
|
||||||
def unicornHook ( **kw ):
|
|
||||||
plugins.kwUnicornHook( 'plugins.clockTree'
|
|
||||||
, 'ClockTree'
|
|
||||||
, 'Build a buffered H-Tree for the clock'
|
|
||||||
, sys.modules[__name__].__file__
|
|
||||||
, **kw
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def ScriptMain ( **kw ):
|
|
||||||
try:
|
|
||||||
errorCode = 0
|
|
||||||
|
|
||||||
print ' o Cleaning up any previous run.'
|
|
||||||
for fileName in os.listdir('.'):
|
|
||||||
if fileName.endswith('.ap'):
|
|
||||||
print ' - <%s>' % fileName
|
|
||||||
os.unlink(fileName)
|
|
||||||
|
|
||||||
cell = None
|
|
||||||
if kw.has_key('cell') and kw['cell']:
|
|
||||||
cell = kw['cell']
|
|
||||||
|
|
||||||
editor = None
|
|
||||||
if kw.has_key('editor') and kw['editor']:
|
|
||||||
editor = kw['editor']
|
|
||||||
print ' o Editor detected, running in graphic mode.'
|
|
||||||
if cell == None: cell = editor.getCell()
|
|
||||||
|
|
||||||
if cell == None:
|
|
||||||
raise ErrorMessage( 3, 'ClockTree: No cell loaded yet.' )
|
|
||||||
|
|
||||||
framework = CRL.AllianceFramework.get()
|
|
||||||
cellGauge = framework.getCellGauge()
|
|
||||||
|
|
||||||
if cell.getAbutmentBox().isEmpty():
|
|
||||||
spaceMargin = Cfg.getParamPercentage('nimbus.spaceMargin').asPercentage() / 100.0 + 0.02
|
|
||||||
aspectRatio = Cfg.getParamPercentage('nimbus.aspectRatio').asPercentage() / 100.0
|
|
||||||
computeAbutmentBox( cell, spaceMargin, aspectRatio, cellGauge )
|
|
||||||
if editor: editor.fit()
|
|
||||||
|
|
||||||
ht = HTree.create( cell, cell.getAbutmentBox() )
|
|
||||||
if editor: editor.refresh()
|
|
||||||
mauka = Mauka.MaukaEngine.create( cell )
|
|
||||||
mauka.run()
|
|
||||||
mauka.destroy()
|
|
||||||
ht.connectLeaf()
|
|
||||||
ht.save()
|
|
||||||
|
|
||||||
#showNet( cell, 'ck_htree_bl_bl_bl' )
|
|
||||||
#showNet( cell, 'ck_htree_bl_bl_br' )
|
|
||||||
#showNet( cell, 'ck_htree_bl_bl_tl' )
|
|
||||||
#showNet( cell, 'ck_htree_bl_bl_tr' )
|
|
||||||
|
|
||||||
except ErrorMessage, e:
|
|
||||||
print e; errorCode = e.code
|
|
||||||
except Exception, e:
|
|
||||||
print '\n\n', e; errorCode = 1
|
|
||||||
traceback.print_tb(sys.exc_info()[2])
|
|
||||||
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
ScriptMain()
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
|
@ -137,10 +137,10 @@ void Plug::setNet(Net* net)
|
||||||
if (net != getNet()) {
|
if (net != getNet()) {
|
||||||
|
|
||||||
if (net && (getCell() != net->getCell()))
|
if (net && (getCell() != net->getCell()))
|
||||||
throw Error("Can't change net of plug : net : " + getString(net) + "does not belong to the cell : " + getString(getCell()));
|
throw Error("Can't change net of plug: " + getString(net) + " does not belong to " + getString(getCell()));
|
||||||
|
|
||||||
if (!getBodyHook()->getSlaveHooks().isEmpty())
|
if (!getBodyHook()->getSlaveHooks().isEmpty())
|
||||||
throw Error("Can't change net of plug : not empty slave hooks");
|
throw Error("Can't change net of plug: not empty slave hooks");
|
||||||
|
|
||||||
_setNet(net);
|
_setNet(net);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "hurricane/Segment.h"
|
#include "hurricane/Segment.h"
|
||||||
#include "hurricane/BasicLayer.h"
|
#include "hurricane/BasicLayer.h"
|
||||||
#include "hurricane/Error.h"
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
|
||||||
namespace Hurricane {
|
namespace Hurricane {
|
||||||
|
|
||||||
|
@ -173,16 +174,20 @@ Segment::Segment(Net* net, Component* source, Component* target, const Layer* la
|
||||||
{
|
{
|
||||||
if (source) {
|
if (source) {
|
||||||
if (!source->getNet())
|
if (!source->getNet())
|
||||||
throw Error("Can't create " + _TName("Segment") + " : unconnected source");
|
throw Error("Can't create " + _TName("Segment") + ": unconnected source");
|
||||||
if (source->getNet() != net)
|
if (source->getNet() != net)
|
||||||
throw Error("Can't create " + _TName("Segment") + " : incompatible source");
|
throw Error( "Can't create " + _TName("Segment") + ": incompatible source \n"
|
||||||
|
+ " - Source:" + getString(source->getNet()) + "\n"
|
||||||
|
+ " - Owner: " + getString(net) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target) {
|
if (target) {
|
||||||
if (!target->getNet())
|
if (!target->getNet())
|
||||||
throw Error("Can't create " + _TName("Segment") + " : unconnected target");
|
throw Error("Can't create " + _TName("Segment") + ": unconnected target");
|
||||||
if (target->getNet() != net)
|
if (target->getNet() != net)
|
||||||
throw Error("Can't create " + _TName("Segment") + " : incompatible target");
|
throw Error( "Can't create " + _TName("Segment") + ": incompatible target\n"
|
||||||
|
+ " - Target:" + getString(target->getNet()) + "\n"
|
||||||
|
+ " - Owner: " + getString(net) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_layer)
|
if (!_layer)
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace Hurricane {
|
||||||
|
|
||||||
// Accessors.
|
// Accessors.
|
||||||
public:
|
public:
|
||||||
|
inline Occurrence getRootNetOccurrence () const;
|
||||||
|
|
||||||
// Predicates.
|
// Predicates.
|
||||||
public:
|
public:
|
||||||
|
@ -71,6 +72,8 @@ namespace Hurricane {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Occurrence DeepNet::getRootNetOccurrence() const { return _netOccurrence; }
|
||||||
|
|
||||||
Net* getDeepNet(HyperNet& hyperNet);
|
Net* getDeepNet(HyperNet& hyperNet);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -750,8 +750,6 @@ extern "C" {
|
||||||
PyModule_AddObject ( module, "TransistorLayer" , (PyObject*)&PyTypeTransistorLayer );
|
PyModule_AddObject ( module, "TransistorLayer" , (PyObject*)&PyTypeTransistorLayer );
|
||||||
Py_INCREF ( &PyTypeViaLayer );
|
Py_INCREF ( &PyTypeViaLayer );
|
||||||
PyModule_AddObject ( module, "ViaLayer" , (PyObject*)&PyTypeViaLayer );
|
PyModule_AddObject ( module, "ViaLayer" , (PyObject*)&PyTypeViaLayer );
|
||||||
Py_INCREF ( &PyTypeContactLayer );
|
|
||||||
PyModule_AddObject ( module, "ContactLayer" , (PyObject*)&PyTypeContactLayer );
|
|
||||||
Py_INCREF ( &PyTypeNetExternalComponents );
|
Py_INCREF ( &PyTypeNetExternalComponents );
|
||||||
PyModule_AddObject ( module, "NetExternalComponents", (PyObject*)&PyTypeNetExternalComponents );
|
PyModule_AddObject ( module, "NetExternalComponents", (PyObject*)&PyTypeNetExternalComponents );
|
||||||
Py_INCREF ( &PyTypeDebugSession );
|
Py_INCREF ( &PyTypeDebugSession );
|
||||||
|
@ -770,7 +768,7 @@ extern "C" {
|
||||||
Py_INCREF ( &PyTypeHookCollection );
|
Py_INCREF ( &PyTypeHookCollection );
|
||||||
PyModule_AddObject ( module, "HookCollection" , (PyObject*)&PyTypeHookCollection );
|
PyModule_AddObject ( module, "HookCollection" , (PyObject*)&PyTypeHookCollection );
|
||||||
Py_INCREF ( &PyTypePlug );
|
Py_INCREF ( &PyTypePlug );
|
||||||
PyModule_AddObject ( module, "PyPlug" , (PyObject*)&PyTypePlug );
|
PyModule_AddObject ( module, "Plug" , (PyObject*)&PyTypePlug );
|
||||||
Py_INCREF ( &PyTypeRoutingPad );
|
Py_INCREF ( &PyTypeRoutingPad );
|
||||||
PyModule_AddObject ( module, "RoutingPad" , (PyObject*)&PyTypeRoutingPad );
|
PyModule_AddObject ( module, "RoutingPad" , (PyObject*)&PyTypeRoutingPad );
|
||||||
Py_INCREF ( &PyTypeVertical );
|
Py_INCREF ( &PyTypeVertical );
|
||||||
|
|
|
@ -1953,8 +1953,8 @@ namespace Katabatic {
|
||||||
} else {
|
} else {
|
||||||
if (vertical->getWidth() != verticalWidth) {
|
if (vertical->getWidth() != verticalWidth) {
|
||||||
cerr << Warning("Segment %s has non-default width %s."
|
cerr << Warning("Segment %s has non-default width %s."
|
||||||
,getString(horizontal).c_str()
|
,getString(vertical).c_str()
|
||||||
,DbU::getValueString(horizontal->getWidth()).c_str()) << endl;
|
,DbU::getValueString(vertical->getWidth()).c_str()) << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,7 @@ namespace {
|
||||||
|
|
||||||
if (netType == Net::Type::CLOCK) {
|
if (netType == Net::Type::CLOCK) {
|
||||||
if (_ckoName.isEmpty()) {
|
if (_ckoName.isEmpty()) {
|
||||||
|
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
|
||||||
_ckoName = inet->getName();
|
_ckoName = inet->getName();
|
||||||
_cko = *inet;
|
_cko = *inet;
|
||||||
} else {
|
} else {
|
||||||
|
@ -282,7 +283,7 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_vddi) == NULL) cerr << Error("Missing <vdd> net at top block level." ) << endl;
|
if (_vddi == NULL) cerr << Error("Missing <vdd> net at top block level." ) << endl;
|
||||||
else destroyRing( _vddi );
|
else destroyRing( _vddi );
|
||||||
if (_vssi == NULL) cerr << Error("Missing <vss> net at top block level." ) << endl;
|
if (_vssi == NULL) cerr << Error("Missing <vss> net at top block level." ) << endl;
|
||||||
else destroyRing( _vssi );
|
else destroyRing( _vssi );
|
||||||
|
@ -362,7 +363,7 @@ namespace {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
//cerr << path << "+" << upNet << endl;
|
//cerr << path << "+" << upNet << endl;
|
||||||
|
|
||||||
if ( (upNet == NULL) or not upNet->isExternal() ) return NULL;
|
if ( (upNet == NULL) or not upNet->isExternal() ) return _blockage;
|
||||||
if ( path.isEmpty() ) break;
|
if ( path.isEmpty() ) break;
|
||||||
|
|
||||||
instance = path.getTailInstance();
|
instance = path.getTailInstance();
|
||||||
|
@ -467,19 +468,21 @@ namespace {
|
||||||
public:
|
public:
|
||||||
typedef map<const BasicLayer*,Plane*,BasicLayer::CompareByMask> PlanesMap;
|
typedef map<const BasicLayer*,Plane*,BasicLayer::CompareByMask> PlanesMap;
|
||||||
public:
|
public:
|
||||||
PowerRailsPlanes ( KiteEngine* );
|
PowerRailsPlanes ( KiteEngine* );
|
||||||
~PowerRailsPlanes ();
|
~PowerRailsPlanes ();
|
||||||
inline Net* getRootNet ( Net*, Path );
|
inline Net* getRootNet ( Net*, Path );
|
||||||
bool hasPlane ( const BasicLayer* );
|
bool hasPlane ( const BasicLayer* );
|
||||||
bool setActivePlane ( const BasicLayer* );
|
bool setActivePlane ( const BasicLayer* );
|
||||||
inline Plane* getActivePlane () const;
|
inline Plane* getActivePlane () const;
|
||||||
void merge ( const Box&, Net* );
|
inline Plane* getActiveBlockagePlane () const;
|
||||||
void doLayout ();
|
void merge ( const Box&, Net* );
|
||||||
|
void doLayout ();
|
||||||
private:
|
private:
|
||||||
KiteEngine* _kite;
|
KiteEngine* _kite;
|
||||||
GlobalNetTable _globalNets;
|
GlobalNetTable _globalNets;
|
||||||
PlanesMap _planes;
|
PlanesMap _planes;
|
||||||
Plane* _activePlane;
|
Plane* _activePlane;
|
||||||
|
Plane* _activeBlockagePlane;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -496,12 +499,12 @@ namespace {
|
||||||
<< " " << ((getDirection()==KbHorizontal) ? "Horizontal" : "Vertical")<< endl;
|
<< " " << ((getDirection()==KbHorizontal) ? "Horizontal" : "Vertical")<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; }
|
inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; }
|
||||||
inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; }
|
inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; }
|
||||||
inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; }
|
inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; }
|
||||||
inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); }
|
inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); }
|
||||||
inline unsigned int PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); }
|
inline unsigned int PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); }
|
||||||
inline Net* PowerRailsPlanes::Rail::getNet () const { return _rails->getNet(); }
|
inline Net* PowerRailsPlanes::Rail::getNet () const { return _rails->getNet(); }
|
||||||
|
|
||||||
|
|
||||||
void PowerRailsPlanes::Rail::merge ( DbU::Unit source, DbU::Unit target )
|
void PowerRailsPlanes::Rail::merge ( DbU::Unit source, DbU::Unit target )
|
||||||
|
@ -845,10 +848,11 @@ namespace {
|
||||||
|
|
||||||
|
|
||||||
PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite )
|
PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite )
|
||||||
: _kite (kite)
|
: _kite (kite)
|
||||||
, _globalNets (kite)
|
, _globalNets (kite)
|
||||||
, _planes ()
|
, _planes ()
|
||||||
, _activePlane(NULL)
|
, _activePlane (NULL)
|
||||||
|
, _activeBlockagePlane(NULL)
|
||||||
{
|
{
|
||||||
_globalNets.setBlockage( kite->getBlockageNet() );
|
_globalNets.setBlockage( kite->getBlockageNet() );
|
||||||
|
|
||||||
|
@ -899,9 +903,16 @@ namespace {
|
||||||
bool PowerRailsPlanes::setActivePlane ( const BasicLayer* layer )
|
bool PowerRailsPlanes::setActivePlane ( const BasicLayer* layer )
|
||||||
{
|
{
|
||||||
PlanesMap::iterator iplane = _planes.find(layer);
|
PlanesMap::iterator iplane = _planes.find(layer);
|
||||||
if ( iplane == _planes.end() ) return false;
|
if (iplane == _planes.end()) return false;
|
||||||
|
|
||||||
_activePlane = iplane->second;
|
_activePlane = iplane->second;
|
||||||
|
_activeBlockagePlane = NULL;
|
||||||
|
if (layer->getMaterial() != BasicLayer::Material::blockage) {
|
||||||
|
BasicLayer* blockageLayer = layer->getBlockageLayer();
|
||||||
|
PlanesMap::iterator ibplane = _planes.find(blockageLayer);
|
||||||
|
if (ibplane != _planes.end())
|
||||||
|
_activeBlockagePlane = ibplane->second;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -910,17 +921,24 @@ namespace {
|
||||||
{ return _activePlane; }
|
{ return _activePlane; }
|
||||||
|
|
||||||
|
|
||||||
|
inline PowerRailsPlanes::Plane* PowerRailsPlanes::getActiveBlockagePlane () const
|
||||||
|
{ return _activeBlockagePlane; }
|
||||||
|
|
||||||
|
|
||||||
void PowerRailsPlanes::merge ( const Box& bb, Net* net )
|
void PowerRailsPlanes::merge ( const Box& bb, Net* net )
|
||||||
{
|
{
|
||||||
if ( not _activePlane ) return;
|
if (not _activePlane) return;
|
||||||
|
|
||||||
Net* topGlobalNet = _globalNets.getRootNet ( net, Path() );
|
Net* topGlobalNet = _globalNets.getRootNet( net, Path() );
|
||||||
if ( topGlobalNet == NULL ) {
|
if (topGlobalNet == NULL) {
|
||||||
ltrace(300) << "Not a global net: " << net << endl;
|
ltrace(300) << "Not a global net: " << net << endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_activePlane->merge ( bb, topGlobalNet );
|
if ( (topGlobalNet == _globalNets.getBlockage()) and (_activeBlockagePlane != NULL) )
|
||||||
|
_activeBlockagePlane->merge( bb, topGlobalNet );
|
||||||
|
else
|
||||||
|
_activePlane->merge( bb, topGlobalNet );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1017,7 +1035,6 @@ namespace {
|
||||||
|
|
||||||
cmess1 << " - PowerRails in " << activePlane->getLayer()->getName() << " ..." << endl;
|
cmess1 << " - PowerRails in " << activePlane->getLayer()->getName() << " ..." << endl;
|
||||||
Query::doQuery();
|
Query::doQuery();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "hurricane/Vertical.h"
|
#include "hurricane/Vertical.h"
|
||||||
#include "hurricane/RoutingPad.h"
|
#include "hurricane/RoutingPad.h"
|
||||||
#include "hurricane/NetExternalComponents.h"
|
#include "hurricane/NetExternalComponents.h"
|
||||||
|
#include "hurricane/DeepNet.h"
|
||||||
#include "hurricane/Instance.h"
|
#include "hurricane/Instance.h"
|
||||||
#include "hurricane/Plug.h"
|
#include "hurricane/Plug.h"
|
||||||
#include "hurricane/Path.h"
|
#include "hurricane/Path.h"
|
||||||
|
@ -62,6 +63,7 @@ namespace Kite {
|
||||||
using Hurricane::Vertical;
|
using Hurricane::Vertical;
|
||||||
using Hurricane::RoutingPad;
|
using Hurricane::RoutingPad;
|
||||||
using Hurricane::NetExternalComponents;
|
using Hurricane::NetExternalComponents;
|
||||||
|
using Hurricane::DeepNet;
|
||||||
using Hurricane::Instance;
|
using Hurricane::Instance;
|
||||||
using Hurricane::Plug;
|
using Hurricane::Plug;
|
||||||
using Hurricane::Path;
|
using Hurricane::Path;
|
||||||
|
@ -85,63 +87,93 @@ namespace Kite {
|
||||||
|
|
||||||
void KiteEngine::buildPreRouteds ()
|
void KiteEngine::buildPreRouteds ()
|
||||||
{
|
{
|
||||||
|
cmess1 << " o Looking for fixed or manually global routed nets." << endl;
|
||||||
|
|
||||||
forEach ( Net*, inet, getCell()->getNets() ) {
|
forEach ( Net*, inet, getCell()->getNets() ) {
|
||||||
if (*inet == _blockageNet) continue;
|
if (*inet == _blockageNet) continue;
|
||||||
if (inet->getType() == Net::Type::POWER ) continue;
|
if (inet->getType() == Net::Type::POWER ) continue;
|
||||||
if (inet->getType() == Net::Type::GROUND) continue;
|
if (inet->getType() == Net::Type::GROUND) continue;
|
||||||
// Don't consider the clock.
|
// Don't skip the clock.
|
||||||
|
|
||||||
vector<Segment*> segments;
|
vector<Segment*> segments;
|
||||||
vector<Contact*> contacts;
|
vector<Contact*> contacts;
|
||||||
|
|
||||||
bool isPreRouted = false;
|
bool isPreRouted = false;
|
||||||
size_t rpCount = 0;
|
bool isFixed = false;
|
||||||
forEach ( Component*, icomponent, inet->getComponents() ) {
|
size_t rpCount = 0;
|
||||||
Horizontal* horizontal = dynamic_cast<Horizontal*>(*icomponent);
|
|
||||||
if (horizontal) {
|
if (inet->isDeepNet()) {
|
||||||
segments.push_back( horizontal );
|
rpCount = 2;
|
||||||
isPreRouted = true;
|
|
||||||
} else {
|
Net* rootNet = dynamic_cast<Net*>(
|
||||||
Vertical* vertical = dynamic_cast<Vertical*>(*icomponent);
|
dynamic_cast<DeepNet*>(*inet)->getRootNetOccurrence().getEntity() );
|
||||||
if (vertical) {
|
forEach ( Component*, icomponent, rootNet->getComponents() ) {
|
||||||
|
if (dynamic_cast<Horizontal*>(*icomponent)) { isFixed = true; break; }
|
||||||
|
if (dynamic_cast<Vertical*> (*icomponent)) { isFixed = true; break; }
|
||||||
|
if (dynamic_cast<Contact*> (*icomponent)) { isFixed = true; break; }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
forEach ( Component*, icomponent, inet->getComponents() ) {
|
||||||
|
Horizontal* horizontal = dynamic_cast<Horizontal*>(*icomponent);
|
||||||
|
if (horizontal) {
|
||||||
|
segments.push_back( horizontal );
|
||||||
isPreRouted = true;
|
isPreRouted = true;
|
||||||
segments.push_back( vertical );
|
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
|
||||||
|
isFixed = true;
|
||||||
} else {
|
} else {
|
||||||
Contact* contact = dynamic_cast<Contact*>(*icomponent);
|
Vertical* vertical = dynamic_cast<Vertical*>(*icomponent);
|
||||||
if (contact) {
|
if (vertical) {
|
||||||
isPreRouted = true;
|
isPreRouted = true;
|
||||||
contacts.push_back( contact );
|
segments.push_back( vertical );
|
||||||
|
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
|
||||||
|
isFixed = true;
|
||||||
} else {
|
} else {
|
||||||
RoutingPad* rp = dynamic_cast<RoutingPad*>(*icomponent);
|
Contact* contact = dynamic_cast<Contact*>(*icomponent);
|
||||||
if (rp) {
|
if (contact) {
|
||||||
++rpCount;
|
isPreRouted = true;
|
||||||
|
contacts.push_back( contact );
|
||||||
|
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
|
||||||
|
or (contact->getHeight() != Session::getViaWidth(contact->getLayer())) )
|
||||||
|
isFixed = true;
|
||||||
} else {
|
} else {
|
||||||
// Plug* plug = dynamic_cast<Plug*>(*icomponent);
|
RoutingPad* rp = dynamic_cast<RoutingPad*>(*icomponent);
|
||||||
// if (plug) {
|
if (rp) {
|
||||||
// cerr << "buildPreRouteds(): " << plug << endl;
|
++rpCount;
|
||||||
// ++rpCount;
|
} else {
|
||||||
// }
|
// Plug* plug = dynamic_cast<Plug*>(*icomponent);
|
||||||
|
// if (plug) {
|
||||||
|
// cerr << "buildPreRouteds(): " << plug << endl;
|
||||||
|
// ++rpCount;
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPreRouted or (rpCount < 2)) {
|
if (isFixed or isPreRouted or (rpCount < 2)) {
|
||||||
NetRoutingState* state = getRoutingState( *inet, Katabatic::KbCreate );
|
NetRoutingState* state = getRoutingState( *inet, Katabatic::KbCreate );
|
||||||
state->setFlags ( NetRoutingState::ManualGlobalRoute );
|
|
||||||
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
|
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
|
||||||
|
state->setFlags ( NetRoutingState::ManualGlobalRoute );
|
||||||
|
|
||||||
if (rpCount > 1) {
|
if (isFixed) {
|
||||||
for ( auto icontact : contacts ) {
|
cmess2 << " - <" << (*inet)->getName() << "> is fixed." << endl;
|
||||||
AutoContact::createFrom( icontact );
|
state->unsetFlags( NetRoutingState::ManualGlobalRoute );
|
||||||
}
|
state->setFlags ( NetRoutingState::Fixed );
|
||||||
|
} else {
|
||||||
for ( auto isegment : segments ) {
|
if (rpCount > 1) {
|
||||||
AutoContact* source = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getSource() ));
|
cmess2 << " - <" << (*inet)->getName() << "> is manually global routed." << endl;
|
||||||
AutoContact* target = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getTarget() ));
|
for ( auto icontact : contacts ) {
|
||||||
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment );
|
AutoContact::createFrom( icontact );
|
||||||
autoSegment->setFlags( Katabatic::SegUserDefined|Katabatic::SegAxisSet );
|
}
|
||||||
|
|
||||||
|
for ( auto isegment : segments ) {
|
||||||
|
AutoContact* source = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getSource() ));
|
||||||
|
AutoContact* target = Session::base()->lookup( dynamic_cast<Contact*>( isegment->getTarget() ));
|
||||||
|
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment );
|
||||||
|
autoSegment->setFlags( Katabatic::SegUserDefined|Katabatic::SegAxisSet );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue