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:
Jean-Paul Chaput 2019-03-23 11:05:51 +01:00
parent 5dd235b3cd
commit 3a2916b5e6
7 changed files with 107 additions and 17 deletions

View File

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

View File

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

View File

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

View File

@ -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".

View File

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

View File

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

View File

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