Improved clock-tree support for variable pitch routing gauges.
* New: In Hurricane::Isobar::PySegment, added wrapper for getOppositeAnchor(). * Bug: CRL::PyRoutingLayerGauge, Python wrapper of getTrackPosition() was in fact returning getTrackNumer(). * Bug: In Katana::PowerRailsPlanes::Rail::doLayout(), add the half minimum distance to the blockage segments extensions. Was causing too near VIAs is cmos45. * Change: In cumulus/plugins/ClockTree, correctly manage routing gauge when the lower pitches (M2/M3) is different from the upper one (M4/M5). But we still can only do sxlib compliant gauges because we do not handle a switch in preferred routing directions.
This commit is contained in:
parent
5dd235b3cd
commit
3a2916b5e6
|
@ -267,9 +267,7 @@ namespace CRL {
|
||||||
|
|
||||||
|
|
||||||
DbU::Unit RoutingLayerGauge::getTrackPosition ( DbU::Unit start, unsigned depth ) const
|
DbU::Unit RoutingLayerGauge::getTrackPosition ( DbU::Unit start, unsigned depth ) const
|
||||||
{
|
{ return depth * _pitch + _offset + start; }
|
||||||
return depth * _pitch + _offset + start;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
string RoutingLayerGauge::_getTypeName () const
|
string RoutingLayerGauge::_getTypeName () const
|
||||||
|
|
|
@ -245,7 +245,7 @@ extern "C" {
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
|
|
||||||
if (PyArg_ParseTuple( args, "OI:RoutingLayerGauge.getTrackIndex", &pyStart, &depth)) {
|
if (PyArg_ParseTuple( args, "OI:RoutingLayerGauge.getTrackIndex", &pyStart, &depth)) {
|
||||||
trackPosition = rlg->getTrackNumber( PyAny_AsLong(pyStart), depth);
|
trackPosition = rlg->getTrackPosition( PyAny_AsLong(pyStart), depth);
|
||||||
} else {
|
} else {
|
||||||
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingLayerGauge.getTrackPosition()." );
|
PyErr_SetString ( ConstructorError, "Bad parameters given to RoutingLayerGauge.getTrackPosition()." );
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -20,6 +20,7 @@ try:
|
||||||
import math
|
import math
|
||||||
import Cfg
|
import Cfg
|
||||||
import Hurricane
|
import Hurricane
|
||||||
|
from Hurricane import Breakpoint
|
||||||
import Viewer
|
import Viewer
|
||||||
import CRL
|
import CRL
|
||||||
from CRL import RoutingLayerGauge
|
from CRL import RoutingLayerGauge
|
||||||
|
@ -58,8 +59,8 @@ def unicornHook ( **kw ):
|
||||||
kw['beforeAction'] = 'placeAndRoute.placeChip'
|
kw['beforeAction'] = 'placeAndRoute.placeChip'
|
||||||
|
|
||||||
plugins.kwUnicornHook( 'placeAndRoute.clockTree'
|
plugins.kwUnicornHook( 'placeAndRoute.clockTree'
|
||||||
, 'Clock Tree'
|
, 'Place Block && Clock Tree'
|
||||||
, 'Build a buffered H-Tree for the clock'
|
, 'Place a block with a buffered H-Tree for the clock'
|
||||||
, sys.modules[__name__].__file__
|
, sys.modules[__name__].__file__
|
||||||
, **kw
|
, **kw
|
||||||
)
|
)
|
||||||
|
|
|
@ -176,6 +176,20 @@ class GaugeConf ( object ):
|
||||||
, self._routingGauge.getLayerGauge(depth).getViaWidth()
|
, self._routingGauge.getLayerGauge(depth).getViaWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _getNearestHorizontalTrack ( self, bb, y, flags ):
|
||||||
|
if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth
|
||||||
|
else: depth = self._horizontalDepth
|
||||||
|
|
||||||
|
index = self._routingGauge.getLayerGauge(depth).getTrackIndex( bb.getYMin(), bb.getYMax(), y, RoutingLayerGauge.Nearest )
|
||||||
|
return self._routingGauge.getLayerGauge(depth).getTrackPosition( bb.getYMin(), index )
|
||||||
|
|
||||||
|
def _getNearestVerticalTrack ( self, bb, x, flags ):
|
||||||
|
if flags & GaugeConf.DeepDepth: depth = self._verticalDeepDepth
|
||||||
|
else: depth = self._verticalDepth
|
||||||
|
|
||||||
|
index = self._routingGauge.getLayerGauge(depth).getTrackIndex( bb.getXMin(), bb.getXMax(), x, RoutingLayerGauge.Nearest )
|
||||||
|
return self._routingGauge.getLayerGauge(depth).getTrackPosition( bb.getXMin(), index )
|
||||||
|
|
||||||
def _createHorizontal ( self, source, target, y, flags ):
|
def _createHorizontal ( self, source, target, y, flags ):
|
||||||
if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth
|
if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth
|
||||||
else: depth = self._horizontalDepth
|
else: depth = self._horizontalDepth
|
||||||
|
@ -309,6 +323,25 @@ class GaugeConf ( object ):
|
||||||
def _rpAccessByPlugName ( self, instance, plugName, net, flags=0 ):
|
def _rpAccessByPlugName ( self, instance, plugName, net, flags=0 ):
|
||||||
return self._rpAccess( self._rpByPlugName(instance,plugName,net), flags )
|
return self._rpAccess( self._rpByPlugName(instance,plugName,net), flags )
|
||||||
|
|
||||||
|
def _setStackPosition ( self, topContact, x, y ):
|
||||||
|
topContact.setX( x )
|
||||||
|
topContact.setY( y )
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for component in topContact.getSlaveComponents():
|
||||||
|
segment = component
|
||||||
|
count += 1
|
||||||
|
if count != 1:
|
||||||
|
print ErrorMessage( 1, 'GaugeConf::_setStackPosition(): There must be exactly one segment connected, not %d.' % count)
|
||||||
|
|
||||||
|
if isinstance(segment,Horizontal):
|
||||||
|
segment.setY( y )
|
||||||
|
segment.getOppositeAnchor( topContact ).setY( y )
|
||||||
|
elif isinstance(segment,Vertical):
|
||||||
|
segment.setX( x )
|
||||||
|
segment.getOppositeAnchor( topContact ).setX( x )
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# Class : "Configuration.GaugeConfWrapper".
|
# Class : "Configuration.GaugeConfWrapper".
|
||||||
|
@ -364,6 +397,15 @@ class GaugeConfWrapper ( object ):
|
||||||
def createVertical ( self, source, target, x, flags=0 ):
|
def createVertical ( self, source, target, x, flags=0 ):
|
||||||
return self._gaugeConf._createVertical( source, target, x, flags )
|
return self._gaugeConf._createVertical( source, target, x, flags )
|
||||||
|
|
||||||
|
def getNearestHorizontalTrack ( self, bb, y, flags ):
|
||||||
|
return self._gaugeConf._getNearestHorizontalTrack ( bb, y, flags )
|
||||||
|
|
||||||
|
def getNearestVerticalTrack ( self, bb, x, flags ):
|
||||||
|
return self._gaugeConf._getNearestVerticalTrack( bb, x, flags )
|
||||||
|
|
||||||
|
def setStackPosition ( self, topContact, x, y ):
|
||||||
|
self._gaugeConf._setStackPosition( topContact, x, y )
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# Class : "Configuration.ChipConf".
|
# Class : "Configuration.ChipConf".
|
||||||
|
|
|
@ -87,7 +87,8 @@ class HTree ( GaugeConfWrapper ):
|
||||||
% aspectRatio )
|
% aspectRatio )
|
||||||
|
|
||||||
ht = HTree( conf, cell, clockNet, clockBox )
|
ht = HTree( conf, cell, clockNet, clockBox )
|
||||||
print ' o Creating Clock H-Tree for <%s>.' % cell.getName()
|
print ' o Creating clock H-Tree for "%s".' % cell.getName()
|
||||||
|
print ' - Clock is "%s"' % ht.masterClock.getName()
|
||||||
ht.build()
|
ht.build()
|
||||||
trace( 550, '\tht.build() OK\n' )
|
trace( 550, '\tht.build() OK\n' )
|
||||||
ht.place()
|
ht.place()
|
||||||
|
@ -482,6 +483,8 @@ class HTreeNode ( object ):
|
||||||
leafCk = deepPlug.getMasterNet()
|
leafCk = deepPlug.getMasterNet()
|
||||||
plugOccurrence.getEntity().setNet( leafCk )
|
plugOccurrence.getEntity().setNet( leafCk )
|
||||||
|
|
||||||
|
trace( 550, '\tLeaf clock set to <%s>.\n' % plugOccurrence.getEntity() )
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def getLeafBufferUnder ( self, point ):
|
def getLeafBufferUnder ( self, point ):
|
||||||
|
@ -526,12 +529,34 @@ class HTreeNode ( object ):
|
||||||
trContact = self.topTree.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet )
|
trContact = self.topTree.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet )
|
||||||
leftContact = self.topTree.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() )
|
leftContact = self.topTree.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() )
|
||||||
rightContact = self.topTree.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() )
|
rightContact = self.topTree.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() )
|
||||||
self.topTree.createHorizontal( leftContact , leftSourceContact, leftSourceContact.getY() , 0 )
|
|
||||||
self.topTree.createHorizontal( rightSourceContact, rightContact , rightSourceContact.getY(), 0 )
|
leftSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftSourceContact.getX(), 0 )
|
||||||
self.topTree.createVertical ( leftContact , blContact , leftContact.getX() , 0 )
|
leftSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, leftSourceContact.getY(), 0 )
|
||||||
self.topTree.createVertical ( tlContact , leftContact , leftContact.getX() , 0 )
|
rightSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightSourceContact.getX(), 0 )
|
||||||
self.topTree.createVertical ( rightContact , brContact , rightContact.getX() , 0 )
|
rightSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, rightSourceContact.getY(), 0 )
|
||||||
self.topTree.createVertical ( trContact , rightContact , rightContact.getX() , 0 )
|
leftX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftContact.getX(), 0 )
|
||||||
|
rightX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightContact.getX(), 0 )
|
||||||
|
tlY = self.topTree.getNearestHorizontalTrack( self.topTree.area, tlContact.getY(), 0 )
|
||||||
|
blY = self.topTree.getNearestHorizontalTrack( self.topTree.area, blContact.getY(), 0 )
|
||||||
|
|
||||||
|
self.topTree.setStackPosition( leftSourceContact, leftSourceX, leftSourceY )
|
||||||
|
self.topTree.setStackPosition( rightSourceContact, rightSourceX, rightSourceY )
|
||||||
|
self.topTree.setStackPosition( tlContact, leftX, tlY )
|
||||||
|
self.topTree.setStackPosition( blContact, leftX, blY )
|
||||||
|
self.topTree.setStackPosition( trContact, rightX, tlY )
|
||||||
|
self.topTree.setStackPosition( brContact, rightX, blY )
|
||||||
|
|
||||||
|
leftContact .setX( leftX )
|
||||||
|
leftContact .setY( leftSourceY )
|
||||||
|
rightContact.setX( rightX )
|
||||||
|
rightContact.setY( rightSourceY )
|
||||||
|
|
||||||
|
self.topTree.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 )
|
||||||
|
self.topTree.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 )
|
||||||
|
self.topTree.createVertical ( leftContact , blContact , leftX , 0 )
|
||||||
|
self.topTree.createVertical ( tlContact , leftContact , leftX , 0 )
|
||||||
|
self.topTree.createVertical ( rightContact , brContact , rightX , 0 )
|
||||||
|
self.topTree.createVertical ( trContact , rightContact , rightX , 0 )
|
||||||
|
|
||||||
for child in self.childs: child.route()
|
for child in self.childs: child.route()
|
||||||
return
|
return
|
||||||
|
|
|
@ -73,7 +73,7 @@ extern "C" {
|
||||||
if (pyReturnHook == NULL) return NULL;
|
if (pyReturnHook == NULL) return NULL;
|
||||||
|
|
||||||
PyObject* pyHook = NULL;
|
PyObject* pyHook = NULL;
|
||||||
if (not PyArg_ParseTuple(args,"O:Hook.merge", &pyHook)) return NULL;
|
if (not PyArg_ParseTuple(args,"O:Segment.getOppositetHook", &pyHook)) return NULL;
|
||||||
|
|
||||||
Hook* hook = PYHOOK_O(pyHook);
|
Hook* hook = PYHOOK_O(pyHook);
|
||||||
|
|
||||||
|
@ -85,6 +85,29 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PySegment_getOppositeAnchor ( PySegment *self, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(20,0) << "PySegment_getOppositeAnchor()" << endl;
|
||||||
|
METHOD_HEAD ( "Segment.getOppositeAnchor()" )
|
||||||
|
|
||||||
|
Component* opposite = NULL;
|
||||||
|
PyObject* pyOpposite = NULL;
|
||||||
|
PyComponent* pyComponent = NULL;
|
||||||
|
if (not PyArg_ParseTuple(args,"O:Segment.getOppositeAnchor", &pyComponent)) return NULL;
|
||||||
|
|
||||||
|
Component* anchor = PYCOMPONENT_O(pyComponent);
|
||||||
|
|
||||||
|
HTRY
|
||||||
|
opposite = segment->getOppositeAnchor( anchor );
|
||||||
|
if (opposite) pyOpposite = PyEntity_NEW( opposite );
|
||||||
|
else
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
HCATCH
|
||||||
|
|
||||||
|
return pyOpposite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject* PySegment_getSource ( PySegment *self )
|
static PyObject* PySegment_getSource ( PySegment *self )
|
||||||
{
|
{
|
||||||
cdebug_log(20,0) << "PySegment_getSource()" << endl;
|
cdebug_log(20,0) << "PySegment_getSource()" << endl;
|
||||||
|
@ -164,6 +187,7 @@ extern "C" {
|
||||||
{ { "getSourceHook" , (PyCFunction)PySegment_getSourceHook , METH_NOARGS , "Return the nested source Hook." }
|
{ { "getSourceHook" , (PyCFunction)PySegment_getSourceHook , METH_NOARGS , "Return the nested source Hook." }
|
||||||
, { "getTargetHook" , (PyCFunction)PySegment_getTargetHook , METH_NOARGS , "Return the nested target Hook." }
|
, { "getTargetHook" , (PyCFunction)PySegment_getTargetHook , METH_NOARGS , "Return the nested target Hook." }
|
||||||
, { "getOppositeHook" , (PyCFunction)PySegment_getOppositeHook , METH_VARARGS, "Return the nested Hook opposite of the argument hook." }
|
, { "getOppositeHook" , (PyCFunction)PySegment_getOppositeHook , METH_VARARGS, "Return the nested Hook opposite of the argument hook." }
|
||||||
|
, { "getOppositeAnchor" , (PyCFunction)PySegment_getOppositeAnchor, METH_VARARGS, "Return the opposite component anchor." }
|
||||||
, { "getSource" , (PyCFunction)PySegment_getSource , METH_NOARGS , "Return the Segment source component (or None)." }
|
, { "getSource" , (PyCFunction)PySegment_getSource , METH_NOARGS , "Return the Segment source component (or None)." }
|
||||||
, { "getTarget" , (PyCFunction)PySegment_getTarget , METH_NOARGS , "Return the Segment target component (or None)." }
|
, { "getTarget" , (PyCFunction)PySegment_getTarget , METH_NOARGS , "Return the Segment target component (or None)." }
|
||||||
, { "getSourceX" , (PyCFunction)PySegment_getSourceX , METH_NOARGS , "Return the Segment source X value." }
|
, { "getSourceX" , (PyCFunction)PySegment_getSourceX , METH_NOARGS , "Return the Segment source X value." }
|
||||||
|
@ -212,7 +236,5 @@ extern "C" {
|
||||||
} // End of extern "C".
|
} // End of extern "C".
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // End of Isobar namespace.
|
} // End of Isobar namespace.
|
||||||
|
|
||||||
|
|
|
@ -638,7 +638,9 @@ namespace {
|
||||||
// - plane->getLayerGauge()->getHalfWireWidth()
|
// - plane->getLayerGauge()->getHalfWireWidth()
|
||||||
// - DbU::fromLambda(0.1);
|
// - DbU::fromLambda(0.1);
|
||||||
DbU::Unit delta = plane->getLayerGauge()->getObstacleDw() - DbU::fromLambda(0.1);
|
DbU::Unit delta = plane->getLayerGauge()->getObstacleDw() - DbU::fromLambda(0.1);
|
||||||
DbU::Unit extension = layer->getExtentionCap();
|
DbU::Unit extension = layer->getExtentionCap() - plane->getLayerGauge()->getLayer()->getMinimalSpacing()/2;
|
||||||
|
//DbU::Unit extension = layer->getExtentionCap() - plane->getLayerGauge()->getHalfPitch() + getHalfWireWidth();
|
||||||
|
//DbU::Unit extension = layer->getExtentionCap();
|
||||||
//DbU::Unit extension = Session::getExtentionCap();
|
//DbU::Unit extension = Session::getExtentionCap();
|
||||||
//unsigned int type = plane->getLayerGauge()->getType();
|
//unsigned int type = plane->getLayerGauge()->getType();
|
||||||
const Box& coronaBb = plane->getKatanaEngine()->getChipTools().getCoronaBb();
|
const Box& coronaBb = plane->getKatanaEngine()->getChipTools().getCoronaBb();
|
||||||
|
|
Loading…
Reference in New Issue