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:
Jean-Paul Chaput 2014-08-15 19:26:49 +02:00
parent fb4a7457a1
commit 51a3236962
9 changed files with 128 additions and 654 deletions

View File

@ -21,6 +21,7 @@
link_directories ( ${CRLCORE_BINARY_DIR}/src/ccore )
# add_executable ( cyclop ${cpps} )
add_executable ( cyclop ${cpps} ${mocCpps} )
target_link_libraries ( cyclop crlcore
${HURRICANE_PYTHON_LIBRARIES}

View File

@ -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)

View File

@ -137,10 +137,10 @@ void Plug::setNet(Net* net)
if (net != getNet()) {
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())
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);
}

View File

@ -20,6 +20,7 @@
#include "hurricane/Segment.h"
#include "hurricane/BasicLayer.h"
#include "hurricane/Error.h"
#include "hurricane/Net.h"
namespace Hurricane {
@ -173,16 +174,20 @@ Segment::Segment(Net* net, Component* source, Component* target, const Layer* la
{
if (source) {
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)
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->getNet())
throw Error("Can't create " + _TName("Segment") + " : unconnected target");
throw Error("Can't create " + _TName("Segment") + ": unconnected target");
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)

View File

@ -60,6 +60,7 @@ namespace Hurricane {
// Accessors.
public:
inline Occurrence getRootNetOccurrence () const;
// Predicates.
public:
@ -71,6 +72,8 @@ namespace Hurricane {
};
inline Occurrence DeepNet::getRootNetOccurrence() const { return _netOccurrence; }
Net* getDeepNet(HyperNet& hyperNet);

View File

@ -750,8 +750,6 @@ extern "C" {
PyModule_AddObject ( module, "TransistorLayer" , (PyObject*)&PyTypeTransistorLayer );
Py_INCREF ( &PyTypeViaLayer );
PyModule_AddObject ( module, "ViaLayer" , (PyObject*)&PyTypeViaLayer );
Py_INCREF ( &PyTypeContactLayer );
PyModule_AddObject ( module, "ContactLayer" , (PyObject*)&PyTypeContactLayer );
Py_INCREF ( &PyTypeNetExternalComponents );
PyModule_AddObject ( module, "NetExternalComponents", (PyObject*)&PyTypeNetExternalComponents );
Py_INCREF ( &PyTypeDebugSession );
@ -770,7 +768,7 @@ extern "C" {
Py_INCREF ( &PyTypeHookCollection );
PyModule_AddObject ( module, "HookCollection" , (PyObject*)&PyTypeHookCollection );
Py_INCREF ( &PyTypePlug );
PyModule_AddObject ( module, "PyPlug" , (PyObject*)&PyTypePlug );
PyModule_AddObject ( module, "Plug" , (PyObject*)&PyTypePlug );
Py_INCREF ( &PyTypeRoutingPad );
PyModule_AddObject ( module, "RoutingPad" , (PyObject*)&PyTypeRoutingPad );
Py_INCREF ( &PyTypeVertical );

View File

@ -1953,8 +1953,8 @@ namespace Katabatic {
} else {
if (vertical->getWidth() != verticalWidth) {
cerr << Warning("Segment %s has non-default width %s."
,getString(horizontal).c_str()
,DbU::getValueString(horizontal->getWidth()).c_str()) << endl;
,getString(vertical).c_str()
,DbU::getValueString(vertical->getWidth()).c_str()) << endl;
}
}

View File

@ -270,6 +270,7 @@ namespace {
if (netType == Net::Type::CLOCK) {
if (_ckoName.isEmpty()) {
cmess1 << " - Using <" << inet->getName() << "> as internal (core) clock net." << endl;
_ckoName = inet->getName();
_cko = *inet;
} 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 );
if (_vssi == NULL) cerr << Error("Missing <vss> net at top block level." ) << endl;
else destroyRing( _vssi );
@ -362,7 +363,7 @@ namespace {
while ( true ) {
//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;
instance = path.getTailInstance();
@ -467,19 +468,21 @@ namespace {
public:
typedef map<const BasicLayer*,Plane*,BasicLayer::CompareByMask> PlanesMap;
public:
PowerRailsPlanes ( KiteEngine* );
~PowerRailsPlanes ();
inline Net* getRootNet ( Net*, Path );
bool hasPlane ( const BasicLayer* );
bool setActivePlane ( const BasicLayer* );
inline Plane* getActivePlane () const;
void merge ( const Box&, Net* );
void doLayout ();
PowerRailsPlanes ( KiteEngine* );
~PowerRailsPlanes ();
inline Net* getRootNet ( Net*, Path );
bool hasPlane ( const BasicLayer* );
bool setActivePlane ( const BasicLayer* );
inline Plane* getActivePlane () const;
inline Plane* getActiveBlockagePlane () const;
void merge ( const Box&, Net* );
void doLayout ();
private:
KiteEngine* _kite;
GlobalNetTable _globalNets;
PlanesMap _planes;
Plane* _activePlane;
Plane* _activeBlockagePlane;
};
@ -496,12 +499,12 @@ namespace {
<< " " << ((getDirection()==KbHorizontal) ? "Horizontal" : "Vertical")<< endl;
}
inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; }
inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; }
inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; }
inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); }
inline unsigned int PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); }
inline Net* PowerRailsPlanes::Rail::getNet () const { return _rails->getNet(); }
inline DbU::Unit PowerRailsPlanes::Rail::getAxis () const { return _axis; }
inline DbU::Unit PowerRailsPlanes::Rail::getWidth () const { return _width; }
inline PowerRailsPlanes::Rails* PowerRailsPlanes::Rail::getRails () const { return _rails; }
inline RoutingPlane* PowerRailsPlanes::Rail::getRoutingPlane () const { return _rails->getRoutingPlane(); }
inline unsigned int PowerRailsPlanes::Rail::getDirection () const { return _rails->getDirection(); }
inline Net* PowerRailsPlanes::Rail::getNet () const { return _rails->getNet(); }
void PowerRailsPlanes::Rail::merge ( DbU::Unit source, DbU::Unit target )
@ -845,10 +848,11 @@ namespace {
PowerRailsPlanes::PowerRailsPlanes ( KiteEngine* kite )
: _kite (kite)
, _globalNets (kite)
, _planes ()
, _activePlane(NULL)
: _kite (kite)
, _globalNets (kite)
, _planes ()
, _activePlane (NULL)
, _activeBlockagePlane(NULL)
{
_globalNets.setBlockage( kite->getBlockageNet() );
@ -899,9 +903,16 @@ namespace {
bool PowerRailsPlanes::setActivePlane ( const BasicLayer* 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;
}
@ -910,17 +921,24 @@ namespace {
{ return _activePlane; }
inline PowerRailsPlanes::Plane* PowerRailsPlanes::getActiveBlockagePlane () const
{ return _activeBlockagePlane; }
void PowerRailsPlanes::merge ( const Box& bb, Net* net )
{
if ( not _activePlane ) return;
if (not _activePlane) return;
Net* topGlobalNet = _globalNets.getRootNet ( net, Path() );
if ( topGlobalNet == NULL ) {
Net* topGlobalNet = _globalNets.getRootNet( net, Path() );
if (topGlobalNet == NULL) {
ltrace(300) << "Not a global net: " << net << endl;
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;
Query::doQuery();
}

View File

@ -26,6 +26,7 @@
#include "hurricane/Vertical.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/NetExternalComponents.h"
#include "hurricane/DeepNet.h"
#include "hurricane/Instance.h"
#include "hurricane/Plug.h"
#include "hurricane/Path.h"
@ -62,6 +63,7 @@ namespace Kite {
using Hurricane::Vertical;
using Hurricane::RoutingPad;
using Hurricane::NetExternalComponents;
using Hurricane::DeepNet;
using Hurricane::Instance;
using Hurricane::Plug;
using Hurricane::Path;
@ -85,63 +87,93 @@ namespace Kite {
void KiteEngine::buildPreRouteds ()
{
cmess1 << " o Looking for fixed or manually global routed nets." << endl;
forEach ( Net*, inet, getCell()->getNets() ) {
if (*inet == _blockageNet) continue;
if (inet->getType() == Net::Type::POWER ) continue;
if (inet->getType() == Net::Type::GROUND) continue;
// Don't consider the clock.
// Don't skip the clock.
vector<Segment*> segments;
vector<Contact*> contacts;
bool isPreRouted = false;
size_t rpCount = 0;
forEach ( Component*, icomponent, inet->getComponents() ) {
Horizontal* horizontal = dynamic_cast<Horizontal*>(*icomponent);
if (horizontal) {
segments.push_back( horizontal );
isPreRouted = true;
} else {
Vertical* vertical = dynamic_cast<Vertical*>(*icomponent);
if (vertical) {
bool isFixed = false;
size_t rpCount = 0;
if (inet->isDeepNet()) {
rpCount = 2;
Net* rootNet = dynamic_cast<Net*>(
dynamic_cast<DeepNet*>(*inet)->getRootNetOccurrence().getEntity() );
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;
segments.push_back( vertical );
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
isFixed = true;
} else {
Contact* contact = dynamic_cast<Contact*>(*icomponent);
if (contact) {
Vertical* vertical = dynamic_cast<Vertical*>(*icomponent);
if (vertical) {
isPreRouted = true;
contacts.push_back( contact );
segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
isFixed = true;
} else {
RoutingPad* rp = dynamic_cast<RoutingPad*>(*icomponent);
if (rp) {
++rpCount;
Contact* contact = dynamic_cast<Contact*>(*icomponent);
if (contact) {
isPreRouted = true;
contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
or (contact->getHeight() != Session::getViaWidth(contact->getLayer())) )
isFixed = true;
} else {
// Plug* plug = dynamic_cast<Plug*>(*icomponent);
// if (plug) {
// cerr << "buildPreRouteds(): " << plug << endl;
// ++rpCount;
// }
RoutingPad* rp = dynamic_cast<RoutingPad*>(*icomponent);
if (rp) {
++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 );
state->setFlags ( NetRoutingState::ManualGlobalRoute );
state->unsetFlags( NetRoutingState::AutomaticGlobalRoute );
state->setFlags ( NetRoutingState::ManualGlobalRoute );
if (rpCount > 1) {
for ( auto icontact : contacts ) {
AutoContact::createFrom( icontact );
}
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 );
if (isFixed) {
cmess2 << " - <" << (*inet)->getName() << "> is fixed." << endl;
state->unsetFlags( NetRoutingState::ManualGlobalRoute );
state->setFlags ( NetRoutingState::Fixed );
} else {
if (rpCount > 1) {
cmess2 << " - <" << (*inet)->getName() << "> is manually global routed." << endl;
for ( auto icontact : contacts ) {
AutoContact::createFrom( icontact );
}
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 );
}
}
}
}