diff --git a/crlcore/etc/cmos/plugins.conf b/crlcore/etc/cmos/plugins.conf new file mode 100644 index 00000000..bcf10a46 --- /dev/null +++ b/crlcore/etc/cmos/plugins.conf @@ -0,0 +1,16 @@ +# -*- Mode:Python; explicit-buffer-name: "plugins.conf" -*- + +import helpers + +# Contains the layout (shared by all technologies). +#execfile( helpers.sysConfDir+'/common/plugins.conf' ) + + +# Parameters for chip plugin. +parametersTable = \ + ( ("chip.block.rails.count" ,TypeInt ,4 ) + , ("chip.block.rails.hWidth" ,TypeInt ,12 ) + , ("chip.block.rails.vWidth" ,TypeInt ,12 ) + , ("chip.block.rails.hSpacing" ,TypeInt ,6 ) + , ("chip.block.rails.vSpacing" ,TypeInt ,6 ) + ) diff --git a/crlcore/src/crlcore/coriolisInit.py b/crlcore/src/crlcore/coriolisInit.py index 0942b165..c08f22e2 100644 --- a/crlcore/src/crlcore/coriolisInit.py +++ b/crlcore/src/crlcore/coriolisInit.py @@ -111,6 +111,7 @@ def coriolisConfigure(): , (helpers.sysConfDir+'/'+symbolicTechno+'/mauka.conf' , SystemFile|ConfigurationHelper) , (helpers.sysConfDir+'/'+symbolicTechno+'/kite.conf' , SystemFile|ConfigurationHelper) , (helpers.sysConfDir+'/'+symbolicTechno+'/stratus1.conf', SystemFile|ConfigurationHelper) + , (helpers.sysConfDir+'/'+symbolicTechno+'/plugins.conf' , SystemFile|ConfigurationHelper) ] if os.getenv('HOME'): confFiles += [ (os.getenv('HOME')+'/.coriolis2.conf', 0) ] diff --git a/crlcore/src/pyCRL/PyAllianceFramework.cpp b/crlcore/src/pyCRL/PyAllianceFramework.cpp index 94fc0650..eccb3dcc 100644 --- a/crlcore/src/pyCRL/PyAllianceFramework.cpp +++ b/crlcore/src/pyCRL/PyAllianceFramework.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// Copyright (c) UPMC/LIP6 2010-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -260,6 +259,27 @@ extern "C" { } + static PyObject* PyAllianceFramework_isPad ( PyAllianceFramework* self, PyObject* args ) + { + trace << "PyAllianceFramework_isPad ()" << endl; + + char* name = NULL; + + HTRY + METHOD_HEAD("AllianceFramework.isPad()") + + if ( not PyArg_ParseTuple(args,"s",&name) ) { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Cell AllianceFramework.isPad()."); + return NULL; + } + + if (af->isPad(name)) Py_RETURN_TRUE; + HCATCH + + Py_RETURN_FALSE; + } + + extern PyObject* PyAllianceFramework_addRoutingGauge ( PyAllianceFramework* self, PyObject* args ) { trace << "PyAllianceFramework_addRoutingGauge ()" << endl; @@ -366,6 +386,8 @@ extern "C" { , "Saves an Alliance Cell." } , { "createCell" , (PyCFunction)PyAllianceFramework_createCell , METH_VARARGS , "Create a Cell in the Alliance framework." } + , { "isPad" , (PyCFunction)PyAllianceFramework_isPad , METH_VARARGS + , "Tells if a cell name is a Pad." } , { "addCellGauge" , (PyCFunction)PyAllianceFramework_addCellGauge , METH_VARARGS , "Add a new cell gauge." } , { "getCellGauge" , (PyCFunction)PyAllianceFramework_getCellGauge , METH_VARARGS diff --git a/crlcore/src/pyCRL/PyRoutingGauge.cpp b/crlcore/src/pyCRL/PyRoutingGauge.cpp index c38f59df..27e550c9 100644 --- a/crlcore/src/pyCRL/PyRoutingGauge.cpp +++ b/crlcore/src/pyCRL/PyRoutingGauge.cpp @@ -44,7 +44,7 @@ namespace CRL { using Isobar::Converter; using Isobar::PyLayer; using Isobar::PyTypeLayer; - using Isobar::PyLayer_Link; + using Isobar::PyLayer_LinkDerived; using Isobar::PyTechnology; using Isobar::PyTypeTechnology; using Isobar::PyTechnology_Link; @@ -238,7 +238,7 @@ extern "C" { } HCATCH - return PyLayer_Link(layer); + return PyLayer_LinkDerived(layer); } @@ -265,7 +265,7 @@ extern "C" { } HCATCH - return PyLayer_Link(layer); + return PyLayer_LinkDerived(layer); } diff --git a/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp b/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp index 03ceabe9..f45cced5 100644 --- a/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp +++ b/crlcore/src/pyCRL/PyRoutingLayerGauge.cpp @@ -1,8 +1,7 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2012-2012, All Rights Reserved +// Copyright (c) UPMC 2012-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -42,7 +41,7 @@ namespace CRL { using Isobar::__cs; using Isobar::PyLayer; using Isobar::PyTypeLayer; - using Isobar::PyLayer_Link; + using Isobar::PyLayer_LinkDerived; extern "C" { @@ -146,7 +145,7 @@ extern "C" { layer = const_cast(rlg->getLayer()); HCATCH - return PyLayer_Link(layer); + return PyLayer_LinkDerived(layer); } @@ -161,7 +160,7 @@ extern "C" { layer = const_cast(rlg->getBlockageLayer()); HCATCH - return PyLayer_Link(layer); + return PyLayer_LinkDerived(layer); } diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 1e9b234a..8ebb24c5 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -1,12 +1,19 @@ # -*- explicit-buffer-name: "CMakeLists.txt" -*- - set ( pysources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py - ${CMAKE_CURRENT_SOURCE_DIR}/ref.py + set ( pySources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py + ${CMAKE_CURRENT_SOURCE_DIR}/ref.py ) - set ( pyplugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTree.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/Chip.py + set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTree.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipPlugin.py + ) + set ( pyPluginChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/BlockPower.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/BlockCorona.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/PadsCorona.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/Configuration.py ) - install ( FILES ${pysources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) - install ( FILES ${pyplugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) + install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) + install ( FILES ${pyPlugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) + install ( FILES ${pyPluginChip} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/chip ) diff --git a/cumulus/src/plugins/ChipPlugin.py b/cumulus/src/plugins/ChipPlugin.py new file mode 100644 index 00000000..3214b1f5 --- /dev/null +++ b/cumulus/src/plugins/ChipPlugin.py @@ -0,0 +1,171 @@ +#!/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/ChipPlugin.py" | +# +-----------------------------------------------------------------+ + +try: + import sys + import traceback + import os.path + import optparse + import math + import Cfg + import Hurricane + from Hurricane import DataBase + from Hurricane import DbU + from Hurricane import Point + 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 + from Hurricane import Query + import Viewer + import CRL + from CRL import RoutingLayerGauge + from helpers import ErrorMessage + from helpers import WarningMessage + import Nimbus + import Metis + import Mauka + import Katabatic + import Kite + import Unicorn + import plugins + import chip.Configuration + import chip.BlockPower + import chip.BlockCorona + import chip.PadsCorona +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 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) + + +# -------------------------------------------------------------------- +# Plugin working part. + + +class PlaceCore ( chip.Configuration.Wrapper ): + + def __init__ ( self, confWrapper ): + chip.Configuration.Wrapper.__init__( self, confWrapper.conf ) + self.validated = False + return + + + def validate ( self ): + self.validated = True + if len(self.cores) < 1: self.validated = False + + coreAb = self.cores[0].getMasterCell().getAbutmentBox() + if (not coreAb.isEmpty()): + if coreAb.getWidth () < self.coreSize.getWidth() \ + and coreAb.getHeight() < self.coreSize.getHeight(): + self.coreSize = coreAb + else: + print ErrorMessage( 1, [ 'Core %s already have an abutment box, bigger than the requested one:' + % self.cores[0].getName() + , " Cell abutment box: %s" % str(coreAb) + , " Maximum abutment box: %s" % str(self.coreSize) ] ) + self.validated = False + + return self.validated + + + def doFloorplan ( self ): + if not self.validated: return + UpdateSession.open() + self.cores[0].getMasterCell().setAbutmentBox( self.coreSize ) + x = (self.chipSize.getWidth () - self.coreSize.getWidth ()) / 2 + y = (self.chipSize.getHeight() - self.coreSize.getHeight()) / 2 + self.cores[0].setTransformation ( Transformation(x,y,Transformation.Orientation.ID) ) + self.cores[0].setPlacementStatus( Instance.PlacementStatus.FIXED ) + UpdateSession.close() + return + + + def doPlacement ( self ): + if not self.validated: return + + checkUnplaced = plugins.CheckUnplaced( self.cores[0].getMasterCell(), plugins.NoFlags ) + if not checkUnplaced.check(): return + + mauka = Mauka.MaukaEngine.create( self.cores[0].getMasterCell() ) + mauka.run() + mauka.destroy() + return + + + + +# -------------------------------------------------------------------- +# Plugin hook functions, unicornHook:menus, ScritMain:call + +def unicornHook ( **kw ): + plugins.kwUnicornHook( 'plugins.chip' + , 'Chip Placement' + , 'Place a Complete Chip (pads && core)' + , sys.modules[__name__].__file__ + , **kw + ) + return + + +def ScriptMain ( **kw ): + try: + cell, editor = plugins.kwParseMain( **kw ) + + conf = chip.Configuration.loadConfiguration( cell ) + if not conf.isValid(): return + + padsCorona = chip.PadsCorona.Corona( conf ) + if not padsCorona.validate(): return + + padsCorona.doLayout() + placeCore = PlaceCore( conf ) + placeCore.validate() + placeCore.doFloorplan() + placeCore.doPlacement() + corePower = chip.BlockPower.Block( Path(conf.cores[0]), conf.vddi, conf.vssi ) + corePower.queryPower() + corePower.doLayout() + coreCorona = chip.BlockCorona.Corona( corePower ) + coreCorona.connectPads( padsCorona ) + coreCorona.connectBlock() + coreCorona.doLayout() + editor.fit() + + except ErrorMessage, e: + print e; errorCode = e.code + editor.fit() + except Exception, e: + print '\n\n', e; errorCode = 1 + traceback.print_tb(sys.exc_info()[2]) + + return 0 diff --git a/cumulus/src/plugins/ClockTree.py b/cumulus/src/plugins/ClockTree.py index fc641300..3c22537e 100755 --- a/cumulus/src/plugins/ClockTree.py +++ b/cumulus/src/plugins/ClockTree.py @@ -1,4 +1,17 @@ #!/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 @@ -32,6 +45,7 @@ try: import Katabatic import Kite import Unicorn + import plugins except ImportError, e: module = str(e).split()[-1] @@ -444,19 +458,20 @@ class HTreeNode ( object ): return def route ( self ): - sourceContact = 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(), sourceContact.getY() ) - rightContact = self.topTree._createContact( self.ckNet, brContact.getX(), sourceContact.getY() ) - self.topTree._createHorizontal( leftContact , sourceContact, sourceContact.getY() ) - self.topTree._createHorizontal( sourceContact, rightContact , sourceContact.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() ) + 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 @@ -497,22 +512,17 @@ def computeAbutmentBox ( cell, spaceMargin, aspectRatio, cellGauge ): return abutmentBox -def unicornHook ( editor ): - #print ' o Hooking up ClockTree script.' - moduleFile = sys.modules[__name__].__file__ - if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'): - moduleFile = moduleFile[:-1] - - editor.addToMenu( 'plugins.clockTree' - , 'ClockTree' - , 'Build a buffered H-Tree for the clock' - , moduleFile - ) - #print ' <%s>' % moduleFile +def unicornHook ( **kw ): + plugins.kwUnicornHook( 'plugins.clockTree' + , 'ClockTree' + , 'Build a buffered H-Tree for the clock' + , sys.modules[__name__].__file__ + , **kw + ) return -def ScriptMain ( cell=None ): +def ScriptMain ( **kw ): try: errorCode = 0 @@ -522,10 +532,14 @@ def ScriptMain ( cell=None ): print ' - <%s>' % fileName os.unlink(fileName) + cell = None + if kw.has_key('cell') and kw['cell']: + cell = kw['cell'] + editor = None - if globals().has_key('__editor'): + if kw.has_key('editor') and kw['editor']: + editor = kw['editor'] print ' o Editor detected, running in graphic mode.' - editor = __editor if cell == None: cell = editor.getCell() if cell == None: diff --git a/cumulus/src/plugins/__init__.py b/cumulus/src/plugins/__init__.py new file mode 100644 index 00000000..b76d48e2 --- /dev/null +++ b/cumulus/src/plugins/__init__.py @@ -0,0 +1,155 @@ +# -*- explicit-buffer-name: "__init__.py" -*- +# +# 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/__init__.py" | +# +-----------------------------------------------------------------+ + + +import Cfg +from helpers import ErrorMessage +from helpers import WarningMessage +from Hurricane import Contact +from Hurricane import Path +from Hurricane import Occurrence +from Hurricane import Instance +import CRL +from CRL import RoutingLayerGauge + + +NoFlags = 0000 +ShowWarnings = 0001 +WarningsAreErrors = 0002 + + + +def kwParseMain ( **kw ): + 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'] + if cell == None: cell = editor.getCell() + + if cell == None: + raise ErrorMessage( 3, 'Chip: No cell loaded yet.' ) + + return cell, editor + + +def kwUnicornHook ( menuPath, menuName, menuTip, moduleFile, **kw ): + editor = kw['editor'] + if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'): + moduleFile = moduleFile[:-1] + + editor.addToMenu( menuPath, menuName, menuTip, moduleFile ) + return + + +def getParameter ( pluginName, key ): + if not Cfg.hasParameter(key): + raise ErrorMessage( 1, 'Mandatory parameter <%s> for for plugin <%s> is missing in configuration.' + % (key,pluginName) ) + return Cfg.Configuration.get().getParameter(key) + + +class CheckUnplaced ( object ): + + def __init__ ( self, cell, flags=NoFlags ): + self.cell = cell + self.flags = flags + self.unplaceds = [] + return + + + def _rcheckUnplaced ( self, path, cell ): + for instance in cell.getInstances(): + if instance.getPlacementStatus() == Instance.PlacementStatus.UNPLACED: + self.unplaceds.append( Occurrence(instance,path) ) + + rpath = Path( path, instance ) + self._rcheckUnplaced( rpath, instance.getMasterCell() ) + return + + + def check ( self ): + self._rcheckUnplaced( Path(), self.cell ) + + if self.unplaceds: + if self.flags & (ShowWarnings | WarningsAreErrors): + message = [ 'Some instances are unplaceds:' ] + for occurrence in self.unplaceds: + message += [ '%s' % (occurrence.getCompactString()) ] + error = ErrorMessage( 3, message ) + + if self.flags & WarningsAreErrors: raise error + else: print error + return self.unplaceds + + +class StackedVia ( object ): + + def __init__ ( self, net, depth, x, y, width, height ): + self._hasLayout = False + self._net = net + self._bottomDepth = depth + self._topDepth = depth + self._x = x + self._y = y + self._width = width + self._height = height + self._vias = [] + return + + def mergeDepth ( self, depth ): + if self._hasLayout: + print WarningMessage( 'StackedVia.mergeDepth(): Cannot be called *after* StackVia.doLayout()' ) + return + if depth < self._bottomDepth: self._bottomDepth = depth + if depth > self._topDepth: self._topDepth = depth + return + + def getVia ( self, metal ): + if not self._hasLayout: return None + for via in self._vias: + if via.getLayer().contains(metal): return via + return None + + def doLayout ( self ): + if self._hasLayout: return + self._hasLayout = True + + routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + + if self._bottomDepth == self._topDepth: + self._vias.append( Contact.create( self._net + , routingGauge.getRoutingLayer(self._bottomDepth) + , self._x , self._y + , self._width, self._height + ) ) + else: + for depth in range(self._bottomDepth,self._topDepth): + if depth == self._bottomDepth: + self._vias.append( Contact.create( self._net + , routingGauge.getContactLayer(depth) + , self._x , self._y + , self._width, self._height + ) ) + else: + self._vias.append( Contact.create( self._vias[-1] + , routingGauge.getContactLayer(depth) + , 0 , 0 + , self._width, self._height + ) ) + #print ' Sub-via: ', self._vias[-1] + return diff --git a/cumulus/src/plugins/chip/BlockCorona.py b/cumulus/src/plugins/chip/BlockCorona.py new file mode 100644 index 00000000..f4da8421 --- /dev/null +++ b/cumulus/src/plugins/chip/BlockCorona.py @@ -0,0 +1,489 @@ +#!/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/chip/BlockCorona.py" | +# +-----------------------------------------------------------------+ + + +import bisect +from operator import methodcaller +import Cfg +from Hurricane import DbU +from Hurricane import Point +from Hurricane import Transformation +from Hurricane import Box +from Hurricane import Path +from Hurricane import Occurrence +from Hurricane import UpdateSession +from Hurricane import Net +from Hurricane import Contact +from Hurricane import Horizontal +from Hurricane import Vertical +import CRL +from CRL import RoutingLayerGauge +from helpers import ErrorMessage +from helpers import WarningMessage +from plugins import StackedVia +import chip.BlockPower + + +class Rail ( object ): + + def __init__ ( self, side, order, axis ): + self.side = side + self.order = order + self.axis = axis + self.vias = { } # Key:pos Element: [pos,railContact,blockContact] + return + + @property + def net ( self ): return self.side.getRailNet(self.order) + + +class HorizontalRail ( Rail ): + + def __init__ ( self, side, order, axis ): + Rail.__init__( self, side, order, axis ) + return + + def connect ( self, contact ): + contactBb = contact.getBoundingBox() + if contactBb.getXMin() < self.side.innerBb.getXMin() \ + or contactBb.getXMax() > self.side.innerBb.getXMax(): + raise ErrorMessage( 1, [ '%s is outside rail/corona X range,' % str(contact) + , 'power pad is likely to be to far off west or east.' + , '(corona:%s)' % str(self.side.innerBb) ] ) + + #print ' HorizontalRail.connect() net:%s contact:%s' % (self.net.getName(),str(contact)) + if self.net != contact.getNet(): return False + if self.vias.has_key(contact.getX()): return False + + keys = self.vias.keys() + keys.sort() + insertIndex = bisect.bisect_left( keys, contact.getX() ) + + if len(keys) > 0: + if insertIndex < len(keys): + insertPosition = keys[ insertIndex ] + if contactBb.getXMax() >= self.vias[insertPosition][2].getBoundingBox().getXMin(): + #print 'Reject contact %s intersect NEXT' % str(contact) + return False + if insertIndex > 0: + if self.vias[keys[insertIndex-1]][2].getBoundingBox().getXMax() >= contactBb.getXMin(): + #print 'Reject contact %s intersect PREVIOUS' % str(contact) + return False + + self.vias[ contact.getX() ] = [ contact.getX() + , StackedVia( self.net + , self.side.getLayerDepth(self.side.getHLayer()) + , contact.getX() + , self.axis + , contact.getWidth() + , self.side.hRailWidth + ) + , contact ] + #print ' ADD contact @ [%d %d]' % (DbU.toLambda(contact.getX()), DbU.toLambda(self.axis)) + self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) + return True + + def doLayout ( self ): + for via in self.vias.values(): + via[1].doLayout() + + Horizontal.create( self.side.corner0(self.order) + , self.side.corner1(self.order) + , self.side.getHLayer() + , self.axis + , self.side.hRailWidth + ) + return + + def doLayout ( self ): + #print 'HorizontalRail[%s] @%d' % (self.order,DbU.toLambda(self.axis)) + + railVias = [ self.side.corner0(self.order) + , self.side.corner1(self.order) ] + + for via in self.vias.values(): + via[1].doLayout() + #print ' Connect:', via[2], via[1].getVia( via[2].getLayer() ) + Vertical.create( via[1].getVia( via[2].getLayer() ) + , via[2] + , via[2].getLayer() + , via[2].getX() + , via[2].getWidth() + ) + railVias.append( via[1].getVia( self.side.getVLayer()) ) + + railVias.sort( key=methodcaller('getY') ) + + for i in range(1,len(railVias)): + Horizontal.create( railVias[i-1] + , railVias[i] + , self.side.getHLayer() + , self.axis + , self.side.hRailWidth + ) + return + + +class VerticalRail ( Rail ): + + def __init__ ( self, side, order, axis ): + Rail.__init__( self, side, order, axis ) + return + + def doLayout ( self ): + #print 'VerticalRail[%s] @%d' % (self.order,DbU.toLambda(self.axis)) + + railVias = [ self.side.corner0(self.order) + , self.side.corner1(self.order) ] + + for via in self.vias.values(): + #print ' Connect: ', via[2] + via[1].doLayout() + Horizontal.create( via[1].getVia( via[2].getLayer() ) + , via[2] + , via[2].getLayer() + , via[2].getY() + , via[2].getHeight() + ) + railVias.append( via[1].getVia( self.side.getVLayer()) ) + + railVias.sort( key=methodcaller('getY') ) + + for i in range(1,len(railVias)): + Vertical.create( railVias[i-1] + , railVias[i] + , self.side.getVLayer() + , self.axis + , self.side.vRailWidth + ) + return + + def connect ( self, contact ): + contactBb = contact.getBoundingBox() + if contactBb.getYMin() < self.side.innerBb.getYMin() \ + or contactBb.getYMax() > self.side.innerBb.getYMax(): + raise ErrorMessage( 1, [ '%s is outside rail/corona Y range' % str(contact) + , 'power pad is likely to be to far off north or south.' + , '(corona:%s)' % str(self.side.innerBb) ] ) + + if self.net != contact.getNet(): return False + if self.vias.has_key(contact.getY()): return False + + keys = self.vias.keys() + keys.sort() + insertIndex = bisect.bisect_left( keys, contact.getY() ) + #print 'keys:', keys + + if len(keys) > 0: + if insertIndex < len(keys): + insertPosition = keys[ insertIndex ] + #print 'insertIndex:%d' % insertIndex + #print 'Check NEXT contactBb:%s via:%s' \ + # % ( str(contactBb) + # , str(self.vias[insertPosition][2].getBoundingBox()) ) + if contactBb.getYMax() >= self.vias[insertPosition][2].getBoundingBox().getYMin(): + # print 'Reject %s intersect NEXT' % str(contact) + return False + if insertIndex > 0: + #print 'check PREVIOUS contactBb:%s via:%s' \ + # % ( str(contactBb) + # , str(self.vias[keys[insertIndex-1]][2].getBoundingBox()) ) + if self.vias[keys[insertIndex-1]][2].getBoundingBox().getYMax() >= contactBb.getYMin(): + # print 'Reject %s intersect PREVIOUS' % str(contact) + return False + + self.vias[ contact.getY() ] = [ contact.getY() + , StackedVia( self.net + , self.side.getLayerDepth(self.side.getVLayer()) + , self.axis + , contact.getY() + , self.side.vRailWidth + , contact.getHeight() + ) + , contact ] + #print 'ADD %s' % str(contact) + self.vias[ contact.getY() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) + return True + + +class Side ( object ): + + def __init__ ( self, corona ): + self._corona = corona + return + + @property + def railsNb ( self ): return self._corona._railsNb + @property + def innerBb ( self ): return self._corona._innerBb + @property + def hRailWidth ( self ): return self._corona._hRailWidth + @property + def hRailSpace ( self ): return self._corona._hRailSpace + @property + def vRailWidth ( self ): return self._corona._vRailWidth + @property + def vRailSpace ( self ): return self._corona._vRailSpace + @property + def corners ( self ): return self._corona._corners + + def getLayerDepth ( self, metal ): return self._corona.getLayerDepth(metal) + def getRail ( self, i ): return self._rails[i] + def getRailNet ( self, i ): return self._corona.getRailNet(i) + def getHLayer ( self ): return self._corona.getHLayer() + def getVLayer ( self ): return self._corona.getVLayer() + + def getRailAxis ( self, i ): + raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' ) + + def getInnerRail ( self, i ): + if i >= len(self._rails): + raise ErrorMessage( 1, 'Side.getInnerRail(): no rail %d (only: %d).' % (i,len(self._rails)) ) + return self._rails[i] + + def getOuterRail ( self, i ): + if i >= len(self._rails): + raise ErrorMessage( 1, 'Side.getOuterRail(): no rail %d (only: %d).' % (i,len(self._rails)) ) + return self._rails[-(i+1)] + + def connect ( self, blockSide ): + for terminal in blockSide.terminals: + for rail in self._rails: + rail.connect( terminal[1] ) + return + + def connectPads ( self, padSide ): + halfRails = len(self._rails)/2 + for terminal in padSide._powerContacts: + #print 'Connect pad terminal ', terminal + for i in range(halfRails): + #print ' Connect to [-%i] @%d' % (i, DbU.toLambda(self.getOuterRail(i).axis)) + self.getOuterRail(i).connect( terminal ) + return + + def doLayout ( self ): + for rail in self._rails: rail.doLayout() + return + + +class HorizontalSide ( Side ): + + def __init__ ( self, corona ): + #print 'HorizontalSide.__init__()' + Side.__init__( self, corona ) + + self._rails = [] + for i in range(self.railsNb): + self._rails.append( HorizontalRail(self,i,self.getRailAxis(i)) ) + #print ' Rail [%i] @%d' % (i,DbU.toLambda(self._rails[-1].axis)) + return + + +class SouthSide ( HorizontalSide ): + + def __init__ ( self, corona ): + HorizontalSide.__init__( self, corona ) + return + + def getRailAxis ( self, i ): + return self.innerBb.getYMin() - self.hRailWidth/2 - self.hRailSpace \ + - i*(self.hRailWidth + self.hRailSpace) + + def corner0 ( self, i ): return self.corners[chip.SouthWest ][i] + def corner1 ( self, i ): return self.corners[chip.SouthEast][i] + + +class NorthSide ( HorizontalSide ): + + def __init__ ( self, corona ): + HorizontalSide.__init__( self, corona ) + return + + def getRailAxis ( self, i ): + return self.innerBb.getYMax() + self.hRailWidth/2 + self.hRailSpace \ + + i*(self.hRailWidth + self.hRailSpace) + + def corner0 ( self, i ): return self.corners[chip.NorthWest ][i] + def corner1 ( self, i ): return self.corners[chip.NorthEast][i] + + +class VerticalSide ( Side ): + + def __init__ ( self, corona ): + Side.__init__( self, corona ) + + self._rails = [] + for i in range(self.railsNb): + self._rails.append( VerticalRail(self,i,self.getRailAxis(i)) ) + return + + +class WestSide ( VerticalSide ): + + def __init__ ( self, corona ): + VerticalSide.__init__( self, corona ) + return + + def getRailAxis ( self, i ): + return self.innerBb.getXMin() - self.vRailWidth/2 - self.vRailSpace \ + - i*(self.vRailWidth + self.vRailSpace) + + def corner0 ( self, i ): return self.corners[chip.SouthWest][i] + def corner1 ( self, i ): return self.corners[chip.NorthWest ][i] + + +class EastSide ( VerticalSide ): + + def __init__ ( self, corona ): + VerticalSide.__init__( self, corona ) + return + + def getRailAxis ( self, i ): + return self.innerBb.getXMax() + self.vRailWidth/2 + self.vRailSpace \ + + i*(self.vRailWidth + self.vRailSpace) + + def corner0 ( self, i ): return self.corners[chip.SouthEast][i] + def corner1 ( self, i ): return self.corners[chip.NorthEast ][i] + + +class Corona ( object ): + + def __init__ ( self, block ): + if not isinstance(block,chip.BlockPower.Block): + raise ErrorMessage( 1, 'Attempt to create a Corona on a non-Block object.' ) + + self._framework = CRL.AllianceFramework.get() + self._routingGauge = self._framework.getRoutingGauge() + self._block = block + self._innerBb = self._block.bb + self._block.path.getTransformation().applyOn( self._innerBb ) + + self._railsNb = 4 + self._hRailWidth = DbU.fromLambda( 12.0 ) + self._vRailWidth = DbU.fromLambda( 12.0 ) + self._hRailSpace = DbU.fromLambda( 6.0 ) + self._vRailSpace = DbU.fromLambda( 6.0 ) + self._topLayerDepth = 0 + self._horizontalDepth = 0 + self._verticalDepth = 0 + + self._southSide = SouthSide( self ) + self._northSide = NorthSide( self ) + self._westSide = WestSide ( self ) + self._eastSide = EastSide ( self ) + + self._guessHvLayers() + return + + def _guessHvLayers ( self ): + 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 WarningMessage( 'Gauge top layer not defined, using top of gauge (%d).' \ + % self._routingGauge.getDepth() ) + self._topLayerDepth = self._routingGauge.getDepth() + + 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 + return + + def getLayerDepth ( self, metal ): + return self._routingGauge.getLayerDepth( metal ) + + def getRailNet ( self, i ): + if i % 2: return self._block.vssi + return self._block.vddi + + def getHLayer ( self ): + return self._routingGauge.getLayerGauge( self._horizontalDepth ).getLayer() + + def getVLayer ( self ): + return self._routingGauge.getLayerGauge( self._verticalDepth ).getLayer() + + def connectBlock ( self ): + for plane in self._block.planes.values(): + for side in plane.sides.values(): + self._southSide.connect( side[chip.South] ) + self._northSide.connect( side[chip.North] ) + self._westSide .connect( side[chip.West ] ) + self._eastSide .connect( side[chip.East ] ) + return + + def connectPads ( self, padsCorona ): + self._southSide.connectPads( padsCorona.southSide ) + self._northSide.connectPads( padsCorona.northSide ) + self._eastSide.connectPads( padsCorona.eastSide ) + self._westSide.connectPads( padsCorona.westSide ) + return + + def doLayout ( self ): + self._corners = { chip.SouthWest : [] + , chip.SouthEast : [] + , chip.NorthWest : [] + , chip.NorthEast : [] + } + + contactDepth = self._horizontalDepth + if self._horizontalDepth > self._verticalDepth: + contactDepth = self._verticalDepth + + for i in range(self._railsNb): + xBL = self._westSide .getRail(i).axis + yBL = self._southSide.getRail(i).axis + xTR = self._eastSide .getRail(i).axis + yTR = self._northSide.getRail(i).axis + net = self.getRailNet( i ) + + self._corners[chip.SouthWest].append( + Contact.create( net + , self._routingGauge.getContactLayer(contactDepth) + , xBL, yBL + , self._hRailWidth + , self._vRailWidth + ) ) + self._corners[chip.NorthWest].append( + Contact.create( net + , self._routingGauge.getContactLayer(contactDepth) + , xBL, yTR + , self._hRailWidth + , self._vRailWidth + ) ) + self._corners[chip.SouthEast].append( + Contact.create( net + , self._routingGauge.getContactLayer(contactDepth) + , xTR, yBL + , self._hRailWidth + , self._vRailWidth + ) ) + self._corners[chip.NorthEast].append( + Contact.create( net + , self._routingGauge.getContactLayer(contactDepth) + , xTR, yTR + , self._hRailWidth + , self._vRailWidth + ) ) + + self._southSide.doLayout() + self._northSide.doLayout() + self._westSide .doLayout() + self._eastSide .doLayout() + return diff --git a/cumulus/src/plugins/chip/BlockPower.py b/cumulus/src/plugins/chip/BlockPower.py new file mode 100644 index 00000000..58cb3f83 --- /dev/null +++ b/cumulus/src/plugins/chip/BlockPower.py @@ -0,0 +1,218 @@ +#!/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/chip/BlockPower.py" | +# +-----------------------------------------------------------------+ + + +from Hurricane import DbU +from Hurricane import Point +from Hurricane import Transformation +from Hurricane import Box +from Hurricane import Interval +from Hurricane import Path +from Hurricane import Occurrence +from Hurricane import UpdateSession +from Hurricane import Net +from Hurricane import Contact +from Hurricane import Horizontal +from Hurricane import Vertical +from Hurricane import Query +import CRL +from helpers import ErrorMessage +from helpers import WarningMessage +import chip.Configuration + + +class Side ( object ): + + def __init__ ( self, block, side, net, metal ): + self.block = block + self.side = side + self.net = net + self.metal = metal + self.terminals = [ ] + return + + def addTerminal ( self, position, width ): + toMerge = Interval( position-width/2, position+width/2 ) + + length = len(self.terminals) + imerge = length + ichunk = 0 + + while ichunk < length: + if imerge == length: + if toMerge.getVMax() < self.terminals[ichunk][0].getVMin(): + self.terminals.insert( ichunk, [ toMerge, None ] ) + imerge = ichunk + length += 1 + break + + if toMerge.intersect(self.terminals[ichunk][0]): + imerge = ichunk + self.terminals[ichunk][0].merge( toMerge ) + else: + if toMerge.getVMax() >= self.terminals[ichunk][0].getVMin(): + self.terminals[imerge][0].merge( self.terminals[ichunk][0] ) + del self.terminals[ichunk] + length -= 1 + continue + else: + break + ichunk += 1 + + if ichunk == length: + self.terminals.append( [ toMerge, None ] ) + + return + + def doLayout ( self ): + if self.side == chip.West: + width = 0 + x = self.block.bb.getXMin() + elif self.side == chip.East: + width = 0 + x = self.block.bb.getXMax() + elif self.side == chip.South: + height = 0 + y = self.block.bb.getYMin() + elif self.side == chip.North: + height = 0 + y = self.block.bb.getYMax() + + for terminal in self.terminals: + if self.side == chip.West or self.side == chip.East: + center = Point( x, terminal[0].getCenter() ) + height = terminal[0].getSize() + elif self.side == chip.North or self.side == chip.South: + center = Point( terminal[0].getCenter(), y ) + width = terminal[0].getSize() + + self.block.path.getTransformation().applyOn( center ) + + contact = Contact.create( self.net, self.metal, center.getX(), center.getY(), width, height ) + terminal[ 1 ] = contact + return + + +class Plane ( object ): + + Horizontal = 0001 + Vertical = 0002 + + def __init__ ( self, block, metal ): + self.block = block + self.metal = metal + self.sides = { } + return + + def addTerminal ( self, net, direction, bb ): + if not self.sides.has_key(net): + self.sides[ net ] = [ Side(self.block,chip.North,net,self.metal) + , Side(self.block,chip.South,net,self.metal) + , Side(self.block,chip.East ,net,self.metal) + , Side(self.block,chip.West ,net,self.metal) + ] + sides = self.sides[ net ] + + if direction == Plane.Horizontal: + if bb.getXMin() <= self.block.bb.getXMin(): + sides[chip.West].addTerminal( bb.getCenter().getY(), bb.getHeight() ) + if bb.getXMax() >= self.block.bb.getXMax(): + sides[chip.East].addTerminal( bb.getCenter().getY(), bb.getHeight() ) + + if direction == Plane.Vertical: + if bb.getYMin() <= self.block.bb.getYMin(): + sides[chip.South].addTerminal( bb.getCenter().getX(), bb.getWidth() ) + if bb.getYMax() >= self.block.bb.getYMax(): + sides[chip.North].addTerminal( bb.getCenter().getX(), bb.getWidth() ) + return + + def doLayout ( self ): + for sidesOfNet in self.sides.values(): + for side in sidesOfNet: + side.doLayout() + return + + + +class GoCb ( object ): + + def __init__ ( self, block ): + self.block = block + return + + def __call__ ( self, query, go ): + direction = None + if isinstance(go,Horizontal): direction = Plane.Horizontal + if isinstance(go,Vertical): direction = Plane.Vertical + if not direction: return + + rootNet = None + if go.getNet().getType() == Net.Type.POWER: rootNet = self.block.vddi + if go.getNet().getType() == Net.Type.GROUND: rootNet = self.block.vssi + if not rootNet: return + + if self.block.activePlane: + bb = go.getBoundingBox( self.block.activePlane.metal.getBasicLayer() ) + query.getPath().getTransformation().applyOn( bb ) + self.block.activePlane.addTerminal( rootNet, direction, bb ) + else: + print WarningMessage( 'BlockPower.GoCb() callback called without an active plane.' ) + return + + +class Block ( object ): + + def __init__ ( self, path, vddi, vssi ): + self.path = path + self.cell = self.path.getTailInstance().getMasterCell() + self.bb = self.cell.getAbutmentBox() + self.vddi = vddi + self.vssi = vssi + self.planes = { } + self.activePlane = None + + routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + for layerGauge in routingGauge.getLayerGauges(): + self.planes[ layerGauge.getLayer().getName() ] = Plane( self, layerGauge.getLayer() ) + + return + + + def queryPower ( self ): + if not self.vddi or not self.vssi: + print ErrorMessage( 1, 'Cannot build block power terminals as vddi and/or vss are not known.' ) + return + + goCb = GoCb( self ) + query = Query() + query.setGoCallback( goCb ) + query.setCell( self.cell ) + query.setArea( self.bb ) + query.setFilter( Query.DoComponents|Query.DoTerminalCells ) + + routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + for layerGauge in routingGauge.getLayerGauges(): + self.activePlane = self.planes[ layerGauge.getLayer().getName() ] + query.setBasicLayer( layerGauge.getLayer().getBasicLayer() ) + query.doQuery() + self.activePlane = None + return + + def doLayout ( self ): + UpdateSession.open() + for plane in self.planes.values(): + plane.doLayout() + UpdateSession.close() + return diff --git a/cumulus/src/plugins/chip/Configuration.py b/cumulus/src/plugins/chip/Configuration.py new file mode 100644 index 00000000..3fdacba5 --- /dev/null +++ b/cumulus/src/plugins/chip/Configuration.py @@ -0,0 +1,363 @@ +# -*- explicit-buffer-name: "Configuration.py" -*- +# +# 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/chip/Configuration.py" | +# +-----------------------------------------------------------------+ + + +import sys +import os.path +import Cfg +from Hurricane import DbU +from Hurricane import Box +from Hurricane import Net +import CRL +from helpers import ErrorMessage +from helpers import WarningMessage +from plugins import getParameter + + +class Configuration ( object ): + + @staticmethod + def _readChipSize( chipConfig ): + if not chipConfig.has_key('chip.size'): return Box() + chipSize = chipConfig['chip.size'] + if not isinstance(chipSize,tuple): + print ErrorMessage( 1, 'The Chip size parameter is *not* a tuple.' ) + return Box() + if len(chipSize) != 2: + print ErrorMessage( 1, 'The Chip size parameter is *not* a tuple of exactly two items.' ) + return Box() + return Box( 0, 0, DbU.fromLambda(chipSize[0]), DbU.fromLambda(chipSize[1]) ) + + + @staticmethod + def _readCoreSize( chipConfig ): + if not chipConfig.has_key('core.size'): + print ErrorMessage( 1, 'The Core size parameter is missing.' ) + return Box() + coreSize = chipConfig['core.size'] + if not isinstance(coreSize,tuple): + print ErrorMessage( 1, 'The Core size parameter is *not* a tuple.' ) + return Box() + if len(coreSize) != 2: + print ErrorMessage( 1, 'The Core size parameter is *not* a tuple of exactly two items.' ) + return Box() + return Box( 0, 0, DbU.fromLambda(coreSize[0]), DbU.fromLambda(coreSize[1]) ) + + + def _readPads ( self, chipConfig, keyword ): + if not chipConfig.has_key(keyword): return [] + padNameList = chipConfig[keyword] + if not isinstance(padNameList,list): + print ErrorMessage( 1, 'The "%s" entry is not a list.' ) + return [] + + af = CRL.AllianceFramework.get() + padList = [] + for i in range(len(padNameList)): + if not isinstance(padNameList[i],str): + print ErrorMessage( 1, 'The element [%d] of list %s is *not* a string (skipped).' + % (i,keyword) ) + continue + + instance = self._cell.getInstance( padNameList[i] ) + if not instance: + print ErrorMessage( 1, 'The pad [%d] (%s) of list %s do not exists in netlist (skipped).' + % (i,padNameList[i],keyword) ) + continue + + if (not af.isPad(instance.getMasterCell().getName())): + print ErrorMessage( 1, 'The pad [%d] (%s) of list %s is not an instance of a pad cell (skipped).' + % (i,padNameList[i],keyword) ) + continue + + padList.append( instance ) + + if not self._clockPad and instance.getMasterCell().getName() == 'pck_px': + self._clockPad = instance + + if not self._powerPad and instance.getMasterCell().getName() == 'pvddick_px': + self._powerPad = instance + + return padList + + + def _guessGlobalNet ( self, name, net ): + if name == self._vddeName: self._vdde = net + if name == self._vddiName: self._vddi = net + if name == self._vsseName: self._vsse = net + if name == self._vssiName: self._vssi = net + if name == self._ckiName: self._cki = net + if name == self._ckoName: self._cko = net + if name == self._ckName: self._ck = net + return + + + def __init__ ( self, chipConfig, cell ): + if not isinstance(chipConfig,dict): + raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' ) + + self._validated = True + self._routingGauge = None + self._topLayerDepth = 0 + self._cell = cell + # Block Corona parameters. + self._railsNb = DbU.fromLambda( getParameter('chip','chip.block.rails.count' ).asInt() ) + self._hRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.hWidth' ).asInt() ) + self._vRailWidth = DbU.fromLambda( getParameter('chip','chip.block.rails.vWidth' ).asInt() ) + self._hRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.hSpacing').asInt() ) + self._vRailSpace = DbU.fromLambda( getParameter('chip','chip.block.rails.vSpacing').asInt() ) + # Global net names. + self._vddeName = "vdde" + self._vddiName = "vddi" + self._vsseName = "vsse" + self._vssiName = "vssi" + self._ckiName = "ck" + self._ckoName = "cko" + self._ckName = "pad" + # Global net names. + self._vdde = None + self._vddi = None + self._vsse = None + self._vssi = None + self._cki = None + self._cko = None + self._ck = None + + self._clockPad = None + self._powerPad = None + self._cores = [] + self._southPads = self._readPads( chipConfig, 'pads.south' ) + self._northPads = self._readPads( chipConfig, 'pads.north' ) + self._eastPads = self._readPads( chipConfig, 'pads.east' ) + self._westPads = self._readPads( chipConfig, 'pads.west' ) + self._coreSize = Configuration._readCoreSize( chipConfig ) + self._chipSize = Configuration._readChipSize( chipConfig ) + self._minCorona = DbU.fromLambda( 100 ) + self._padWidth = 0 + self._padHeight = 0 + + self.loadRoutingGauge() + self.checkPads() + self.computeChipSize() + self.findPowerAndClockNets() + return + + + def loadRoutingGauge ( self ): + self._routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + + 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 WarningMessage( 'Gauge top layer not defined, using top of gauge (%d).' \ + % self._routingGauge.getDepth() ) + self._topLayerDepth = self._routingGauge.getDepth() + return + + + def checkPads ( self ): + af = CRL.AllianceFramework.get() + cellPads = [] + for instance in self._cell.getInstances(): + if (af.isPad(instance.getMasterCell().getName())): + cellPads.append( instance ) + else: + self._cores.append( instance ) + + for pad in cellPads: + if pad in self._southPads: continue + if pad in self._northPads: continue + if pad in self._eastPads: continue + if pad in self._westPads: continue + print ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % pad.getName() ) + self._validated = False + + if len(self._cores) < 1: + print ErrorMessage( 1, 'Chip "%s" doesn\'t seems to have a core.' % self._cell.getName() ) + self._validated = False + + if len(self._cores) > 1: + message = [ 'Chip "%s" have more than one core:' % self._cell.getName() ] + for i in range(len(self._cores)): + message.append( '%4d: %s' % (i,self._cores[i].getName()) ) + print ErrorMessage( 1, message ) + self._validated = False + + return + + + def findPowerAndClockNets ( self ): + if self._powerPad: + for plug in self._powerPad.getPlugs(): + masterNet = plug.getMasterNet() + netType = masterNet.getType() + if netType != Net.Type.POWER \ + and netType != Net.Type.GROUND \ + and netType != Net.Type.CLOCK: + continue + + net = plug.getNet() + if not net: + net = self._cell.getNet( masterNet.getName() ) + if not net: + print ErrorMessage( 1, 'Missing global net <%s> at chip level.' % masterNet.getName() ) + self._validated = False + continue + self._guessGlobalNet( masterNet.getName(), net ) + + if self._clockPad: + for plug in self._powerPad.getPlugs(): + masterNet = plug.getMasterNet() + netType = masterNet.getType() + net = plug.getNet() + + if not net: + net = self._cell.getNet( masterNet.getName() ) + if not net: + print ErrorMessage( 1, 'Missing global net <%s> at chip level.' % masterNet.getName() ) + self._validated = False + continue + + if masterNet.getName() == self._ckName: + self._guessGlobalNet( masterNet.getName(), net ) + return + + + def computeChipSize ( self ): + if not self._clockPad: + print ErrorMessage( 1, 'There must be at least one pad of model "pck_px" to be used as reference.' ) + self._validated = False + return False + + self._padHeight = self._clockPad.getMasterCell().getAbutmentBox().getHeight() + self._padWidth = self._clockPad.getMasterCell().getAbutmentBox().getWidth() + + if not self._chipSize.isEmpty(): return + + horizontalPads = max( len(self._southPads), len(self._northPads) ) + verticalPads = max( len(self._eastPads ), len(self._westPads ) ) + self._chipSize = Box( 0 + , 0 + , self._padWidth * horizontalPads + 2*self._padHeight + , self._padWidth * verticalPads + 2*self._padHeight + ) + return + + def getSpecialNetRoot ( self, net ): + if net.getName() == self._vddeName: return self._vdde + if net.getName() == self._vsseName: return self._vsse + if net.getType() == Net.Type.POWER: return self._vddi + if net.getType() == Net.Type.GROUND: return self._vssi + return None + + +class Wrapper ( object ): + + def __init__ ( self, conf ): + if not isinstance(conf,Configuration): + raise ErrorMessage('Attempt to create a Wrapper() from non-Configuration object.') + self._conf = conf + return + + def isValid ( self ): return self._conf._validated + + @property + def conf ( self ): return self._conf + + @property + def routingGauge ( self ): return self._conf._routingGauge + @property + def topLayerDepth ( self ): return self._conf._topLayerDepth + + @property + def cell ( self ): return self._conf._cell + + # Global Net names. + @property + def vddeName ( self ): return self._conf._vddeName + @property + def vsseName ( self ): return self._conf._vsseName + @property + def vddiName ( self ): return self._conf._vddiName + @property + def vssiName ( self ): return self._conf._vssiName + @property + def ckiName ( self ): return self._conf._ckiName + @property + def ckoName ( self ): return self._conf._ckoName + @property + def ckName ( self ): return self._conf._ckName + + # Global Nets. + @property + def vdde ( self ): return self._conf._vdde + @property + def vsse ( self ): return self._conf._vsse + @property + def vddi ( self ): return self._conf._vddi + @property + def vssi ( self ): return self._conf._vssi + @property + def cki ( self ): return self._conf._cki + @property + def cko ( self ): return self._conf._cko + @property + def ck ( self ): return self._conf._ck + + # Various. + @property + def clockPad ( self ): return self._conf._clockPad + @property + def powerPad ( self ): return self._conf._powerPad + @property + def cores ( self ): return self._conf._cores + @property + def southPads ( self ): return self._conf._southPads + @property + def northPads ( self ): return self._conf._northPads + @property + def eastPads ( self ): return self._conf._eastPads + @property + def westPads ( self ): return self._conf._westPads + @property + def coreSize ( self ): return self._conf._coreSize + @coreSize.setter + def coreSize ( self, ab ): self._conf._coreSize = ab + @property + def chipSize ( self ): return self._conf._chipSize + @property + def minCorona ( self ): return self._conf._minCorona + @property + def padWidth ( self ): return self._conf._padWidth + @property + def padHeight ( self ): return self._conf._padHeight + + +def loadConfiguration ( cell ): + sys.path.append( os.getcwd() ) + + confFile = cell.getName()+'_chip' + confModule = __import__( confFile, globals(), locals(), confFile ) + + if not confModule.__dict__.has_key('chip'): + raise WarningMessage( 'Module <%s> do not provides the chip variable, skipped.' \ + % confFile ) + + return Wrapper( Configuration( confModule.__dict__['chip'], cell ) ) diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py new file mode 100644 index 00000000..c5d0798c --- /dev/null +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -0,0 +1,393 @@ +#!/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/chip/PadsCorona.py" | +# +-----------------------------------------------------------------+ + + +from operator import itemgetter +import Cfg +from Hurricane import DbU +from Hurricane import Point +from Hurricane import Transformation +from Hurricane import Box +from Hurricane import Path +from Hurricane import Occurrence +from Hurricane import UpdateSession +from Hurricane import Net +from Hurricane import Contact +from Hurricane import Horizontal +from Hurricane import Vertical +from Hurricane import Instance +import CRL +from CRL import RoutingLayerGauge +from helpers import ErrorMessage +from helpers import WarningMessage +import chip.Configuration + + +class Side ( object ): + + def __init__ ( self, corona, sideType ): + self._type = sideType + self._corona = corona + self._powerContacts = [] + + if self._type == chip.North: self._pads = self._corona.northPads + elif self._type == chip.South: self._pads = self._corona.southPads + elif self._type == chip.East: self._pads = self._corona.eastPads + elif self._type == chip.West: self._pads = self._corona.westPads + else: + raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) + return + + + def _toGrid ( self, v ): return v - (v % DbU.fromLambda(5.0)) + + + def getAxis ( self, i ): + if self._type == chip.North: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.South: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] + elif self._type == chip.East: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] + elif self._type == chip.West: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] + else: + raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) + return 0 + + + def _check ( self, checkSize, checkName ): + sideName = 'unknown' + chipSize = 0 + if self._type == chip.North or self._type == chip.South: + chipSize = self._corona.chipSize.getWidth() + sideName = 'wide' + elif self._type == chip.East or self._type == chip.West: + chipSize = self._corona.chipSize.getHeight() + sideName = 'tall' + + if checkSize > chipSize: + print ErrorMessage( 1, [ 'Chip is not %s enought to accomodate the %s,' % (sideName,checkName) + , 'needs %dl, but only has %dl.' + % ( DbU.toLambda(checkSize), DbU.toLambda(chipSize) ) + ] ) + return False + return True + + + def check ( self ): + validated = True + if self._type == chip.North: + self.validated = self._check( self._corona.coreSize.getWidth() + + 2*self._corona.minCorona + + 2*self._corona.padHeight + , 'core' ) + checkName = 'north pads' + elif self._type == chip.East: + self.validated = self._check( self._corona.coreSize.getHeight() + + 2*self._corona.minCorona + + 2*self._corona.padHeight + , 'core' ) + checkName = 'east pads' + elif self._type == chip.South: checkName = 'south pads' + elif self._type == chip.West: checkName = 'west pads' + + validated = self._check( len(self._pads)*self._corona.padWidth + + 2*self._corona.padHeight + , checkName ) and validated + return validated + + + def _createPowerContacts ( self, pad, net ): + if self._type == chip.North or self._type == chip.South: + hvDepth = self._corona.getVDepth() + elif self._type == chip.East or self._type == chip.West: + hvDepth = self._corona.getHDepth() + + masterCell = pad.getMasterCell() + for component in masterCell.getNet(net.getName()).getExternalComponents(): + if component.getBoundingBox().getYMin() > masterCell.getAbutmentBox().getYMin(): continue + if self._corona.routingGauge.getLayerDepth(component.getLayer()) != hvDepth: continue + if not isinstance(component,Vertical): continue + + if self._type == chip.North or self._type == chip.South: + width = component.getWidth() + height = 0 + else: + width = 0 + height = component.getWidth() + + position = Point( component.getX(), masterCell.getAbutmentBox().getYMin() ) + pad.getTransformation().applyOn( position ) + + self._powerContacts.append( Contact.create( net + , component.getLayer() + , position.getX() + , position.getY() + , width + , height + ) ) + return + + + def _createAllPowerContacts ( self ): + for pad in self._pads: + masterCell = pad.getMasterCell() + if masterCell.getName() != 'pvddick_px' \ + and masterCell.getName() != 'pvssick_px' \ + and masterCell.getName() != 'pvddeck_px' \ + and masterCell.getName() != 'pvsseck_px': + continue + #print 'Power pad:', pad + self._createPowerContacts( pad, self._corona.vddi ) + self._createPowerContacts( pad, self._corona.vssi ) + return + + + def _placePads ( self ): + if self._type == chip.North: + hAdvance = True + orientation = Transformation.Orientation.ID + sideLength = self._corona.chipSize.getWidth() + x = self._corona.padHeight + y = self._corona.chipSize.getHeight() - self._corona.padHeight + elif self._type == chip.South: + hAdvance = True + orientation = Transformation.Orientation.MY + sideLength = self._corona.chipSize.getWidth() + x = self._corona.padHeight + y = self._corona.padHeight + elif self._type == chip.East: + hAdvance = False + orientation = Transformation.Orientation.R3 + sideLength = self._corona.chipSize.getHeight() + x = self._corona.chipSize.getWidth() - self._corona.padHeight + y = self._corona.padHeight + self._corona.padWidth + elif self._type == chip.West: + hAdvance = False + orientation = Transformation.Orientation.R1 + sideLength = self._corona.chipSize.getHeight() + x = self._corona.padHeight + y = self._corona.padHeight + + step = (sideLength - 2*self._corona.padHeight) / len(self._pads) + for pad in self._pads: + pad.setTransformation ( Transformation( self._toGrid(x), self._toGrid(y), orientation ) ) + pad.setPlacementStatus( Instance.PlacementStatus.FIXED ) + if hAdvance: x += step + else: y += step + return + + + def _routePads ( self ): + for i in range(len(self._corona._powerRails)): + if self._type == chip.South: + Horizontal.create( self._corona._corners[chip.SouthWest ][i] + , self._corona._corners[chip.SouthEast][i] + , self._corona._powerRails[i][1] + , self.getAxis( i ) + , self._corona._powerRails[i][3] + ) + elif self._type == chip.North: + Horizontal.create( self._corona._corners[chip.NorthWest ][i] + , self._corona._corners[chip.NorthEast][i] + , self._corona._powerRails[i][1] + , self.getAxis( i ) + , self._corona._powerRails[i][3] + ) + elif self._type == chip.East: + Vertical.create( self._corona._corners[chip.SouthEast][i] + , self._corona._corners[chip.NorthEast ][i] + , self._corona._powerRails[i][1] + , self.getAxis( i ) + , self._corona._powerRails[i][3] + ) + elif self._type == chip.West: + Vertical.create( self._corona._corners[chip.SouthWest][i] + , self._corona._corners[chip.NorthWest ][i] + , self._corona._powerRails[i][1] + , self.getAxis( i ) + , self._corona._powerRails[i][3] + ) + return + + def doLayout ( self ): + self._placePads() + self._routePads() + self._createAllPowerContacts() + return + + +class Corona ( chip.Configuration.Wrapper ): + + def __init__ ( self, confWrapper ): + chip.Configuration.Wrapper.__init__( self, confWrapper.conf ) + self.validated = False + self._northSide = Side( self, chip.North ) + self._southSide = Side( self, chip.South ) + self._eastSide = Side( self, chip.East ) + self._westSide = Side( self, chip.West ) + self._corners = { chip.SouthWest : [] + , chip.SouthEast : [] + , chip.NorthWest : [] + , chip.NorthEast : [] + } + self._powerRails = [] # [ , [net, layer, axis, width] ] + + self._locatePadRails() + self._guessHvLayers() + return + + @property + def southSide ( self ): return self._southSide + @property + def northSide ( self ): return self._northSide + @property + def eastSide ( self ): return self._eastSide + @property + def westSide ( self ): return self._westSide + + def getSwCorner ( self, i ): return self._corners[chip.SouthWest][i] + def getSeCorner ( self, i ): return self._corners[chip.SouthEast][i] + def getNwCorner ( self, i ): return self._corners[chip.NorthWest][i] + def getNeCorner ( self, i ): return self._corners[chip.NorthEast][i] + def getRailNet ( self, i ): return self._powerRails[i][0] + def getRailLayer ( self, i ): return self._powerRails[i][1] + def getRailAxis ( self, i ): return self._powerRails[i][2] + def getRailWidth ( self, i ): return self._powerRails[i][3] + def getHDepth ( self ): return self._horizontalDepth + def getVDepth ( self ): return self._verticalDepth + + + def validate ( self ): + self.validated = self._northSide.check() + self.validated = self._southSide.check() and self.validated + self.validated = self._eastSide.check() and self.validated + self.validated = self._westSide.check() and self.validated + return self.validated + + + def _locatePadRails ( self ): + if not self.clockPad: + print ErrorMessage( 1, 'There must be at least one pad of model "pck_px" to guess the pad rails.' ) + return False + + for plug in self.clockPad.getPlugs(): + masterNet = plug.getMasterNet() + netType = masterNet.getType() + net = plug.getNet() + + if netType != Net.Type.POWER \ + and netType != Net.Type.GROUND \ + and netType != Net.Type.CLOCK: + continue + + if not net: + net = self.cell.getNet( masterNet.getName() ) + if not net: + print ErrorMessage( 1, 'Missing global net <%s> at chip level.' % masterNet.getName() ) + continue + + for component in masterNet.getExternalComponents(): + if not isinstance(component,Horizontal): continue + xs = component.getSourcePosition().getX() + xt = component.getTargetPosition().getX() + if xs < xt: length = xt - xs + else: length = xs - xt + if length < self.padWidth*.6: continue + + self._powerRails.append( [ net, component.getLayer(), component.getY(), component.getWidth() ] ) + + self._powerRails.sort( key=itemgetter(2) ) + + #for rail in self._powerRails: + # print 'Pad rail %s @%d width:%d layer:%s' % ( str(rail[0].getName()) + # , DbU.toLambda(rail[2]) + # , DbU.toLambda(rail[3]) + # , str(rail[1].getName()) + # ) + return + + def _guessHvLayers ( self ): + if not self.powerPad: + print ErrorMessage( 1, 'There must be at least one pad of model "pvddick_px" to guess the pad power terminals.' ) + return False + + availableDepths = set() + masterCell = self.powerPad.getMasterCell() + for component in masterCell.getNet('vddi').getExternalComponents(): + if component.getBoundingBox().getYMin() <= masterCell.getAbutmentBox().getYMin(): + availableDepths.add( self.routingGauge.getLayerDepth(component.getLayer()) ) + + #print 'available depth:', availableDepths + + self._horizontalDepth = 0 + self._verticalDepth = 0 + for depth in range(0,self.topLayerDepth+1): + if not depth in availableDepths: continue + + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: + self._horizontalDepth = depth + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: + self._verticalDepth = depth + + #print 'h:', self._horizontalDepth + #print 'v:', self._verticalDepth + return + + + def doLayout ( self ): + if not self.validated: return + UpdateSession.open() + self.cell.setAbutmentBox( self.chipSize ) + + for i in range(len(self._powerRails)): + xBL = self._westSide .getAxis(i) + yBL = self._southSide.getAxis(i) + xTR = self._eastSide .getAxis(i) + yTR = self._northSide.getAxis(i) + + self._corners[chip.SouthWest].append( + Contact.create( self.getRailNet(i) + , self.getRailLayer(i) + , xBL, yBL + , self.getRailWidth(i) + , self.getRailWidth(i) + ) ) + self._corners[chip.NorthWest].append( + Contact.create( self.getRailNet(i) + , self.getRailLayer(i) + , xBL, yTR + , self.getRailWidth(i) + , self.getRailWidth(i) + ) ) + self._corners[chip.SouthEast].append( + Contact.create( self.getRailNet(i) + , self.getRailLayer(i) + , xTR, yBL + , self.getRailWidth(i) + , self.getRailWidth(i) + ) ) + self._corners[chip.NorthEast].append( + Contact.create( self.getRailNet(i) + , self.getRailLayer(i) + , xTR, yTR + , self.getRailWidth(i) + , self.getRailWidth(i) + ) ) + + self._northSide.doLayout() + self._southSide.doLayout() + self._eastSide.doLayout() + self._westSide.doLayout() + + UpdateSession.close() + return diff --git a/cumulus/src/plugins/chip/__init__.py b/cumulus/src/plugins/chip/__init__.py new file mode 100644 index 00000000..0ae5b573 --- /dev/null +++ b/cumulus/src/plugins/chip/__init__.py @@ -0,0 +1,29 @@ +# -*- explicit-buffer-name: "__init__.py" -*- +# +# 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/chip/__init__.py" | +# +-----------------------------------------------------------------+ + + +# Common constants used through all modules. + +# For Corona's sides. +North = 0000 +South = 0001 +East = 0002 +West = 0003 + +# For Corona's corners. +SouthWest = 0000 +SouthEast = 0001 +NorthWest = 0002 +NorthEast = 0003 diff --git a/hurricane/src/hurricane/Query.cpp b/hurricane/src/hurricane/Query.cpp index d10399b2..3e34ed96 100644 --- a/hurricane/src/hurricane/Query.cpp +++ b/hurricane/src/hurricane/Query.cpp @@ -1,7 +1,6 @@ - // -*- C++ -*- // -// Copyright (c) BULL S.A. 2000-2013, All Rights Reserved +// Copyright (c) BULL S.A. 2000-2014, All Rights Reserved // // This file is part of Hurricane. // @@ -19,10 +18,6 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | @@ -35,7 +30,6 @@ #include - #include "hurricane/BasicLayer.h" #include "hurricane/Slice.h" #include "hurricane/Cell.h" @@ -45,15 +39,9 @@ namespace Hurricane { - -// ------------------------------------------------------------------- -// Slave Class : "QueryState". - - // ------------------------------------------------------------------- // Class : "QueryStack". - QueryStack::QueryStack () : vector() //, _tab (" ") diff --git a/hurricane/src/hurricane/hurricane/Query.h b/hurricane/src/hurricane/hurricane/Query.h index b646a88e..9242ee92 100644 --- a/hurricane/src/hurricane/hurricane/Query.h +++ b/hurricane/src/hurricane/hurricane/Query.h @@ -1,7 +1,6 @@ - // -*- C++ -*- // -// Copyright (c) BULL S.A. 2000-2013, All Rights Reserved +// Copyright (c) BULL S.A. 2000-2014, All Rights Reserved // // This file is part of Hurricane. // @@ -19,10 +18,6 @@ // License along with Hurricane. If not, see // . // -// =================================================================== -// -// $Id$ -// // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | @@ -34,22 +29,19 @@ // +-----------------------------------------------------------------+ -#ifndef __QUERY_H__ -#define __QUERY_H__ +#ifndef HURRICANE_QUERY_H +#define HURRICANE_QUERY_H - -#include - -#include "hurricane/Commons.h" -#include "hurricane/Box.h" -#include "hurricane/Transformation.h" -#include "hurricane/Cell.h" -#include "hurricane/Instance.h" +#include +#include "hurricane/Commons.h" +#include "hurricane/Box.h" +#include "hurricane/Transformation.h" +#include "hurricane/Cell.h" +#include "hurricane/Instance.h" namespace Hurricane { - class BasicLayer; class Go; class QueryStack; @@ -58,7 +50,6 @@ namespace Hurricane { // ------------------------------------------------------------------- // Slave Class : "QueryState". - class QueryState { private: inline QueryState ( Locator* locator ); @@ -386,8 +377,6 @@ namespace Hurricane { //inline const Tabulation& Query::getTab () const { return _stack.getTab(); } +} // Hurricane namespace. -} // End of Hurricane namespace. - - -#endif // __QUERY_H__ +#endif // HURRICANE_QUERY_H diff --git a/hurricane/src/isobar/CMakeLists.txt b/hurricane/src/isobar/CMakeLists.txt index 5af6dd11..26b3a673 100644 --- a/hurricane/src/isobar/CMakeLists.txt +++ b/hurricane/src/isobar/CMakeLists.txt @@ -9,6 +9,7 @@ ) set ( sources ProxyProperty.cpp PyBreakpoint.cpp + PyInterval.cpp PyBox.cpp PyCell.cpp PyCellCollection.cpp @@ -72,6 +73,7 @@ ) set ( includes hurricane/isobar/ProxyProperty.h hurricane/isobar/PyBreakpoint.h + hurricane/isobar/PyInterval.h hurricane/isobar/PyBox.h hurricane/isobar/PyCell.h hurricane/isobar/PyCellCollection.h diff --git a/hurricane/src/isobar/PyComponent.cpp b/hurricane/src/isobar/PyComponent.cpp index 091badbc..35227b3e 100644 --- a/hurricane/src/isobar/PyComponent.cpp +++ b/hurricane/src/isobar/PyComponent.cpp @@ -103,7 +103,7 @@ extern "C" { layer = const_cast(component->getLayer ()); HCATCH - return PyLayer_Link ( layer ); + return PyLayer_LinkDerived ( layer ); } diff --git a/hurricane/src/isobar/PyHurricane.cpp b/hurricane/src/isobar/PyHurricane.cpp index 81808d0e..195587f5 100644 --- a/hurricane/src/isobar/PyHurricane.cpp +++ b/hurricane/src/isobar/PyHurricane.cpp @@ -20,6 +20,7 @@ #include "hurricane/isobar/PyUpdateSession.h" #include "hurricane/isobar/PyDbU.h" #include "hurricane/isobar/PyPoint.h" +#include "hurricane/isobar/PyInterval.h" #include "hurricane/isobar/PyBox.h" #include "hurricane/isobar/PyTransformation.h" #include "hurricane/isobar/PyOrientation.h" @@ -501,6 +502,7 @@ extern "C" { PyUpdateSession_LinkPyType (); PyDbU_LinkPyType (); PyPoint_LinkPyType (); + PyInterval_LinkPyType (); PyBox_LinkPyType (); PyTransformation_LinkPyType (); PyOrientation_LinkPyType (); @@ -560,8 +562,9 @@ extern "C" { PYTYPE_READY ( DebugSession ) PYTYPE_READY ( UpdateSession ) - PYTYPE_READY ( Point ) PYTYPE_READY ( DbU ) + PYTYPE_READY ( Point ) + PYTYPE_READY ( Interval ) PYTYPE_READY ( Box ) PYTYPE_READY ( Transformation ) PYTYPE_READY ( Orientation ) @@ -635,6 +638,7 @@ extern "C" { PYTYPE_READY_SUB ( Pad , Component) // Identifier string can take up to 10 characters ! + __cs.addType ( "intv" , &PyTypeInterval , "" , false ); __cs.addType ( "box" , &PyTypeBox , "" , false ); __cs.addType ( "ent" , &PyTypeEntity , "" , false ); __cs.addType ( "cell" , &PyTypeCell , "" , false, "ent" ); @@ -706,9 +710,11 @@ extern "C" { Py_INCREF ( &PyTypeDbU ); PyModule_AddObject ( module, "DbU" , (PyObject*)&PyTypeDbU ); Py_INCREF ( &PyTypePoint ); - PyModule_AddObject ( module, "Box" , (PyObject*)&PyTypeBox ); - Py_INCREF ( &PyTypePoint ); PyModule_AddObject ( module, "Point" , (PyObject*)&PyTypePoint ); + Py_INCREF ( &PyTypeInterval ); + PyModule_AddObject ( module, "Interval" , (PyObject*)&PyTypeInterval ); + Py_INCREF ( &PyTypeBox ); + PyModule_AddObject ( module, "Box" , (PyObject*)&PyTypeBox ); Py_INCREF ( &PyTypeTransformation ); PyModule_AddObject ( module, "Transformation" , (PyObject*)&PyTypeTransformation ); Py_INCREF ( &PyTypePath ); @@ -800,6 +806,7 @@ extern "C" { PyRoutingPad_postModuleInit(); PyNet_postModuleInit(); PyInstance_postModuleInit(); + PyQuery_postModuleInit(); trace << "Hurricane.so loaded " << (void*)&typeid(string) << endl; } diff --git a/hurricane/src/isobar/PyInterval.cpp b/hurricane/src/isobar/PyInterval.cpp new file mode 100644 index 00000000..b45cd1d1 --- /dev/null +++ b/hurricane/src/isobar/PyInterval.cpp @@ -0,0 +1,337 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2014-2014, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +// | =============================================================== | +// | C++ Module : "./PyInterval.cpp" | +// +-----------------------------------------------------------------+ + + +#include "hurricane/isobar/PyPoint.h" +#include "hurricane/isobar/PyInterval.h" + + +namespace Isobar { + +using namespace Hurricane; + +extern "C" { + + +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(Interval,interval,function) + + +// +=================================================================+ +// | "PyInterval" Python Module Code Part | +// +=================================================================+ + +#if defined(__PYTHON_MODULE__) + + + // Standart Accessors (Attributes). + DirectGetLongAttribute(PyInterval_getVMin ,getVMin ,PyInterval,Interval) + DirectGetLongAttribute(PyInterval_getVMax ,getVMax ,PyInterval,Interval) + DirectGetLongAttribute(PyInterval_getCenter ,getCenter ,PyInterval,Interval) + DirectGetLongAttribute(PyInterval_getSize ,getSize ,PyInterval,Interval) + DirectGetLongAttribute(PyInterval_getHalfSize ,getHalfSize ,PyInterval,Interval) + + // Standart Predicates (Attributes). + DirectGetBoolAttribute(PyInterval_isEmpty ,isEmpty ,PyInterval,Interval) + DirectGetBoolAttribute(PyInterval_isPonctual,isPonctual,PyInterval,Interval) + + // Standart Destroy (Attribute). + DirectDestroyAttribute(PyInterval_destroy, PyInterval) + + + // --------------------------------------------------------------- + // Class Method : "PyInterval_NEW ()" + + static PyObject* PyInterval_NEW (PyObject *module, PyObject *args) { + trace << "PyInterval_NEW()" << endl; + + Interval* interval = NULL; + + HTRY + PyObject* arg0; + PyObject* arg1; + PyObject* arg2; + __cs.init ("Interval.Interval"); + + if (not PyArg_ParseTuple( args, "|O&O&O&:Interval.Interval" + , Converter, &arg0 + , Converter, &arg1 + , Converter, &arg2 )) + return NULL; + + if (__cs.getObjectIds() == NO_ARG ) { interval = new Interval (); } + else if (__cs.getObjectIds() == INTS2_ARG) { interval = new Interval ( PyInt_AsLong(arg0) , PyInt_AsLong(arg1) ); } + else if (__cs.getObjectIds() == INTV_ARG ) { interval = new Interval ( *PYINTERVAL_O(arg0) ); } + else { + PyErr_SetString(ConstructorError, "invalid number of parameters for Interval constructor." ); + return NULL; + } + HCATCH + + return PyInterval_Link( interval ); + } + + + static int PyInterval_Init ( PyInterval* self, PyObject* args, PyObject* kwargs ) + { + trace << "PyInterval_Init(): " << (void*)self << endl; + return 0; + } + + + static PyObject* PyInterval_getUnion ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_getUnion()" << endl; + + METHOD_HEAD ( "Interval.getUnion()" ) + + PyInterval* otherPyInterval; + if (PyArg_ParseTuple(args,"O!:Interval.getUnion", &PyTypeInterval, &otherPyInterval)) { + HTRY + Interval* interval = new Interval ( interval->getUnion(*PYINTERVAL_O(otherPyInterval))); + HCATCH + return PyInterval_Link( interval ); + } else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.getUnion."); + } + return NULL; + } + + + static PyObject* PyInterval_getIntersection ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_getIntersection()" << endl; + + METHOD_HEAD ( "Interval.getIntersection()" ) + + PyInterval* otherPyInterval = NULL; + if (PyArg_ParseTuple(args,"O!:Interval.getIntersection", &PyTypeInterval, &otherPyInterval)) { + HTRY + Interval* interval = new Interval(interval->getIntersection(*PYINTERVAL_O(otherPyInterval))); + HCATCH + return PyInterval_Link( interval ); + } else { + PyErr_SetString(ConstructorError, "invalid number of parameters for Interval.getIntersection."); + } + return NULL; + } + + + static PyObject* PyInterval_contains ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_contains ()" << endl; + + METHOD_HEAD( "Interval.contains()" ) + + PyObject* arg0; + bool result = false; + + HTRY + __cs.init("Interval.contains"); + if (not PyArg_ParseTuple(args,"|O&:Interval.contains",Converter,&arg0) ) + return NULL; + + if (__cs.getObjectIds() == INT_ARG ) { result = interval->contains ( PyInt_AsLong(arg0) ); } + else if (__cs.getObjectIds() == INTV_ARG) { result = interval->contains ( *PYINTERVAL_O(arg0) ); } + else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.contains constructor." ); + return NULL; + } + + HCATCH + if (result) Py_RETURN_TRUE; + Py_RETURN_FALSE; + } + + + static PyObject* PyInterval_intersect ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_intersect ()" << endl; + + bool result = false; + HTRY + PyInterval* pyInterval = NULL; + METHOD_HEAD ( "Interval.intersect()" ) + + if (PyArg_ParseTuple(args,"O!:Interval.intersects", &PyTypeInterval, &pyInterval)) { + result = interval->intersect( *PYINTERVAL_O(pyInterval) ); + } else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.intersect." ); + return NULL; + } + + HCATCH + if (result) Py_RETURN_TRUE; + Py_RETURN_FALSE; + } + + + static PyObject* PyInterval_makeEmpty ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_makeEmpty ()" << endl; + + METHOD_HEAD( "Interval.makeEmpty()" ) + interval->makeEmpty(); + + Py_INCREF( self ); + return (PyObject*)self; + } + + + static PyObject* PyInterval_inflate ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_inflate ()" << endl; + + METHOD_HEAD( "Interval.inflate()" ) + + PyObject* arg0; + PyObject* arg1; + + HTRY + __cs.init( "Interval.inflate" ); + if (not PyArg_ParseTuple(args,"|O&O&:Interval.inflate",Converter,&arg0,Converter,&arg1)) + return NULL; + + if (__cs.getObjectIds() == INT_ARG ) { interval->inflate( PyInt_AsLong(arg0) ); } + else if (__cs.getObjectIds() == INTS2_ARG) { interval->inflate( PyInt_AsLong(arg0), PyInt_AsLong(arg1) ); } + else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.inflate()" ); + return NULL; + } + HCATCH + + Py_INCREF( self ); + return (PyObject*)self; + } + + + static PyObject* PyInterval_merge ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_merge ()" << endl; + + METHOD_HEAD( "Interval.merge()" ) + + PyObject* arg0; + PyObject* arg1; + + HTRY + __cs.init( "Interval.merge" ); + if (not PyArg_ParseTuple(args,"|O&O&:Interval.merge",Converter,&arg0,Converter,&arg1)) + return NULL; + + if (__cs.getObjectIds() == INT_ARG ) { interval->merge( PyInt_AsLong(arg0) ); } + else if (__cs.getObjectIds() == INTV_ARG) { interval->merge( *PYINTERVAL_O(arg0) ); } + else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.merge()" ); + return NULL; + } + HCATCH + + Py_INCREF( self ); + return (PyObject*)self; + } + + + static PyObject* PyInterval_intersection ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_intersection ()" << endl; + + METHOD_HEAD( "Interval.intersection()" ) + + PyObject* arg0; + PyObject* arg1; + + HTRY + __cs.init( "Interval.intersection" ); + if (not PyArg_ParseTuple(args,"|O&O&:Interval.intersection",Converter,&arg0,Converter,&arg1)) + return NULL; + + if (__cs.getObjectIds() == INTV_ARG ) { interval->intersection( *PYINTERVAL_O(arg0) ); } + else if (__cs.getObjectIds() == INTS2_ARG) { interval->intersection( PyInt_AsLong(arg0), PyInt_AsLong(arg1) ); } + else { + PyErr_SetString ( ConstructorError, "invalid number of parameters for Interval.intersection()" ); + return NULL; + } + HCATCH + + Py_INCREF( self ); + return (PyObject*)self; + } + + + static PyObject* PyInterval_translate ( PyInterval *self, PyObject* args ) { + trace << "PyInterval_translate ()" << endl; + + HTRY + METHOD_HEAD( "Interval.translate()" ) + DbU::Unit delta = 0; + if (PyArg_ParseTuple(args,"l:Interval.translate", &delta)) { + interval->translate(delta); + } else { + PyErr_SetString( ConstructorError, "invalid number of parameters for Interval.translate()" ); + return NULL; + } + HCATCH + + Py_INCREF( self ); + return (PyObject*)self; + } + + + // --------------------------------------------------------------- + // PyInterval Attribute Method table. + + PyMethodDef PyInterval_Methods[] = + { { "getVMin" , (PyCFunction)PyInterval_getVMin , METH_NOARGS , "Return the VMin value." } + , { "getVMax" , (PyCFunction)PyInterval_getVMax , METH_NOARGS , "Return the VMax value." } + , { "getCenter" , (PyCFunction)PyInterval_getCenter , METH_NOARGS , "Return the interval center value." } + , { "getSize" , (PyCFunction)PyInterval_getSize , METH_NOARGS , "Return the interval length." } + , { "getHalfSize" , (PyCFunction)PyInterval_getHalfSize , METH_NOARGS , "Return the interval half length." } + , { "getUnion" , (PyCFunction)PyInterval_getUnion , METH_VARARGS, "Return the smallest enclosing interval." } + , { "getIntersection", (PyCFunction)PyInterval_getIntersection, METH_VARARGS, "Return the overlapping interval." } + , { "isEmpty" , (PyCFunction)PyInterval_isEmpty , METH_NOARGS , "Return true if the interval is empty." } + , { "isPonctual" , (PyCFunction)PyInterval_isPonctual , METH_NOARGS , "Return true if the interval reduced to a point." } + , { "contains" , (PyCFunction)PyInterval_contains , METH_VARARGS, "Return true if the interval contains the argument." } + , { "intersect" , (PyCFunction)PyInterval_intersect , METH_VARARGS, "Return true if two intervales overlap." } + , { "makeEmpty" , (PyCFunction)PyInterval_makeEmpty , METH_NOARGS , "Transform the interval in an empty one." } + , { "inflate" , (PyCFunction)PyInterval_inflate , METH_VARARGS, "Expand the interval of the given values." } + , { "merge" , (PyCFunction)PyInterval_merge , METH_VARARGS, "Expand or contract the interval to contains the arguments." } + , { "intersection" , (PyCFunction)PyInterval_intersection , METH_VARARGS, "Expand the interval to contains the arguments.." } + , { "translate" , (PyCFunction)PyInterval_translate , METH_VARARGS, "translate the interval." } + , { "destroy" , (PyCFunction)PyInterval_destroy , METH_NOARGS + , "Destroy associated hurricane object, the python object remains." } + , {NULL, NULL, 0, NULL} /* sentinel */ + }; + + // x-------------------------------------------------------------x + // | "PyInterval" Object Methods | + // x-------------------------------------------------------------x + + + DirectDeleteMethod(PyInterval_DeAlloc,PyInterval) + PyTypeObjectLinkPyTypeNewInit(Interval) +//PyTypeObjectLinkPyType(Interval) + +#else // End of Python Module Code Part. + + +// x=================================================================x +// | "PyInterval" Shared Library Code Part | +// x=================================================================x + + + // --------------------------------------------------------------- + // PyInterval Object Definitions. + + LinkCreateMethod(Interval) + PyTypeObjectDefinitions(Interval) + +# endif // End of Shared Library Code Part. + +} // End of extern "C". + +} // End of Isobar namespace. + diff --git a/hurricane/src/isobar/PyLayer.cpp b/hurricane/src/isobar/PyLayer.cpp index 87ca5d20..76e57527 100644 --- a/hurricane/src/isobar/PyLayer.cpp +++ b/hurricane/src/isobar/PyLayer.cpp @@ -1,36 +1,7 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie -// -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2006-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -47,6 +18,11 @@ #include "hurricane/isobar/PyLayer.h" #include "hurricane/isobar/PyLayerMask.h" #include "hurricane/isobar/PyBasicLayer.h" +#include "hurricane/isobar/PyRegularLayer.h" +#include "hurricane/isobar/PyContactLayer.h" +#include "hurricane/isobar/PyViaLayer.h" +#include "hurricane/isobar/PyDiffusionLayer.h" +#include "hurricane/isobar/PyTransistorLayer.h" #include "hurricane/isobar/PyBasicLayerCollection.h" @@ -133,24 +109,7 @@ extern "C" { } \ HCATCH \ \ - return PyLayer_Link(rlayer); \ - } - - -# define accessorLayerFromVoid(FUNC_NAME,PY_SELF_TYPE,SELF_TYPE) \ - static PyObject* PY_SELF_TYPE##_##FUNC_NAME ( PY_SELF_TYPE* self ) \ - { \ - trace << #PY_SELF_TYPE "_" #FUNC_NAME "()" << endl; \ - \ - Layer* rlayer = NULL; \ - \ - HTRY \ - GENERIC_METHOD_HEAD(SELF_TYPE,cobject,#SELF_TYPE"."#FUNC_NAME"()") \ - rlayer = const_cast(cobject->FUNC_NAME()); \ - HCATCH \ - \ - if (rlayer == NULL) Py_RETURN_NONE; \ - return PyLayer_Link(rlayer); \ + return PyLayer_LinkDerived(rlayer); \ } @@ -196,7 +155,7 @@ extern "C" { HCATCH \ \ if (rlayer == NULL) Py_RETURN_NONE; \ - return PyLayer_Link(rlayer); \ + return PyLayer_LinkDerived(rlayer); \ } @@ -409,6 +368,32 @@ extern "C" { } + extern PyObject* PyLayer_LinkDerived ( Layer* object ) + { + if (object == NULL) Py_RETURN_NONE; + + BasicLayer* basicLayer = dynamic_cast(object); + if (basicLayer) return PyBasicLayer_Link(basicLayer); + + ContactLayer* contactLayer = dynamic_cast(object); + if (contactLayer) return PyContactLayer_Link(contactLayer); + + ViaLayer* viaLayer = dynamic_cast(object); + if (viaLayer) return PyViaLayer_Link(viaLayer); + + DiffusionLayer* diffusionLayer = dynamic_cast(object); + if (diffusionLayer) return PyDiffusionLayer_Link(diffusionLayer); + + RegularLayer* regularLayer = dynamic_cast(object); + if (regularLayer) return PyRegularLayer_Link(regularLayer); + + TransistorLayer* transistorLayer = dynamic_cast(object); + if (transistorLayer) return PyTransistorLayer_Link(transistorLayer); + + Py_RETURN_NONE; + } + + #endif // End of Shared Library Code Part. } // extern "C". diff --git a/hurricane/src/isobar/PyPath.cpp b/hurricane/src/isobar/PyPath.cpp index 1b43ea97..fc954fca 100644 --- a/hurricane/src/isobar/PyPath.cpp +++ b/hurricane/src/isobar/PyPath.cpp @@ -298,11 +298,11 @@ extern "C" { , { "getMasterCell" , (PyCFunction)PyPath_getMasterCell , METH_NOARGS , "Returns the master cell referenced by the last instance of the path." } , { "getName" , (PyCFunction)PyPath_getName , METH_NOARGS , "Returns the concatenation of instances names." } , { "getTransformation" , (PyCFunction)PyPath_getTransformation , METH_VARARGS, "Return the resulting transformation." } - , { "getInstances", (PyCFunction)PyPath_getInstances, METH_NOARGS , "Returns the collection of instances defining the path." } + , { "getInstances" , (PyCFunction)PyPath_getInstances , METH_NOARGS , "Returns the collection of instances defining the path." } , { "isEmpty" , (PyCFunction)PyPath_isEmpty , METH_NOARGS , "Return true if the path is empty." } , { "destroy" , (PyCFunction)PyPath_destroy , METH_NOARGS , "Destroy associated hurricane object, the python object remains." } - , {NULL, NULL, 0, NULL} /* sentinel */ + , {NULL, NULL, 0, NULL} /* sentinel */ }; diff --git a/hurricane/src/isobar/PyPoint.cpp b/hurricane/src/isobar/PyPoint.cpp index 37cc4b30..71590fc2 100644 --- a/hurricane/src/isobar/PyPoint.cpp +++ b/hurricane/src/isobar/PyPoint.cpp @@ -130,9 +130,9 @@ extern "C" { PyMethodDef PyPoint_Methods[] = { { "getX" , (PyCFunction)PyPoint_getX , METH_NOARGS , "Return the Point X value." } , { "getY" , (PyCFunction)PyPoint_getY , METH_NOARGS , "Return the Point Y value." } - , { "SetX" , (PyCFunction)PyPoint_SetX , METH_VARARGS, "Modify the Point X value." } - , { "SetY" , (PyCFunction)PyPoint_SetY , METH_VARARGS, "Modify the Point Y value." } - , { "Translate", (PyCFunction)PyPoint_Translate, METH_VARARGS, "Translate the point of dx and dy." } + , { "setX" , (PyCFunction)PyPoint_SetX , METH_VARARGS, "Modify the Point X value." } + , { "setY" , (PyCFunction)PyPoint_SetY , METH_VARARGS, "Modify the Point Y value." } + , { "translate", (PyCFunction)PyPoint_Translate, METH_VARARGS, "Translate the point of dx and dy." } , { "destroy" , (PyCFunction)PyPoint_destroy , METH_NOARGS , "Destroy associated hurricane object The python object remains." } , {NULL, NULL, 0, NULL} /* sentinel */ diff --git a/hurricane/src/isobar/PyQuery.cpp b/hurricane/src/isobar/PyQuery.cpp index eeb792c0..c9121af1 100644 --- a/hurricane/src/isobar/PyQuery.cpp +++ b/hurricane/src/isobar/PyQuery.cpp @@ -1,36 +1,7 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie -// -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2010-2014, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -44,9 +15,11 @@ #include "hurricane/isobar/PyBox.h" +#include "hurricane/isobar/PyPath.h" #include "hurricane/isobar/PyTransformation.h" #include "hurricane/isobar/PyBasicLayer.h" #include "hurricane/isobar/PyCell.h" +#include "hurricane/isobar/PyInstance.h" #include "hurricane/isobar/PyEntity.h" #include "hurricane/isobar/PyQuery.h" #include "hurricane/isobar/PyQueryMask.h" @@ -88,6 +61,12 @@ extern "C" { }; + inline void BaseQuery::setGoCallback ( PyObject* cb ) { _goCallback = cb; } + inline void BaseQuery::setMarkerCallback ( PyObject* cb ) { _markerCallback = cb; } + inline void BaseQuery::setRubberCallback ( PyObject* cb ) { _rubberCallback = cb; } + inline void BaseQuery::setExtensionGoCallback ( PyObject* cb ) { _extensionGoCallback = cb; } + inline void BaseQuery::setMasterCellCallback ( PyObject* cb ) { _masterCellCallback = cb; } + BaseQuery::BaseQuery ( PyQuery* self ) : Query() , _self (self) @@ -98,13 +77,7 @@ extern "C" { , _masterCellCallback (NULL) { } - inline void BaseQuery::setGoCallback ( PyObject* cb ) { _goCallback = cb; cerr << "BaseQuery::setGoCallback()" << endl; } - inline void BaseQuery::setMarkerCallback ( PyObject* cb ) { _markerCallback = cb; } - inline void BaseQuery::setRubberCallback ( PyObject* cb ) { _rubberCallback = cb; } - inline void BaseQuery::setExtensionGoCallback ( PyObject* cb ) { _extensionGoCallback = cb; } - inline void BaseQuery::setMasterCellCallback ( PyObject* cb ) { _masterCellCallback = cb; } - - bool BaseQuery::hasGoCallback () const { cerr << "BaseQuery::hasGoCallback():" << _goCallback << endl; return _goCallback != NULL; } + bool BaseQuery::hasGoCallback () const { return _goCallback != NULL; } bool BaseQuery::hasMarkerCallback () const { return _markerCallback != NULL; } bool BaseQuery::hasRubberCallback () const { return _rubberCallback != NULL; } bool BaseQuery::hasExtensionGoCallback () const { return _extensionGoCallback != NULL; } @@ -112,7 +85,6 @@ extern "C" { void BaseQuery::goCallback ( Go* go ) { - cerr << "BaseQuery::goCallback():" << go << endl; if (PyCallable_Check(_goCallback)) { PyObject_CallFunctionObjArgs( _goCallback, _self, PyEntity_NEW(go), NULL ); } @@ -143,7 +115,7 @@ extern "C" { } -#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(Query,query,function) +#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(BaseQuery,query,function) // +=================================================================+ @@ -153,74 +125,11 @@ extern "C" { #if defined(__PYTHON_MODULE__) -#if 0 - template< typename PySelf, typename Self, typename RType, typename... Args > - class PySetFunctor { - public: - typedef PyObject* (PySet_fp) ( PySelf*, PyObject* ); - typedef RType (Self::* CppSet_fp) ( Args... ); - public: - inline PySet_fp wrapper() const; - private: - static PyObject* _wrapper ( PySelf* self, PyObject* args ) - { - } - private: - CppSet_fp _fp; - string _name; - }; - - template< typename PySelf, typename Self, typename RType, typename... Args > - inline PySetFunctor::PySet_fp PySetFunctor::wrapper() const - { return _wrapper; } -#endif - - // +-------------------------------------------------------------+ // | "PyQuery" Attribute Methods | // +-------------------------------------------------------------+ -#if WORK_IN_PROGRESS - static MethodDefTable pyObjectMethods; - - template< typename CppType, typename PySelf > - inline CppType* getCppObject ( PySelf* self, const string& methodName ) - { - if (self._object == NULL) { - string message = "Attempt to call "+methodName+"on an unbound hurricane object."; - PyErr_SetString( ProxyError, message.c_str() ); - return NULL; - } - - CppType* cppObject = dynamic_cast(self._object); - if (cppObject == NULL) { - string message = "Invalid dynamic_cast<>() in "+methodName+" (internal error)."; - PyErr_SetString( ProxyError, message.c_str() ); - return NULL; - } - return cppObject; - } - - - - template< typename CppType, typename PySelf, typename ReturnType, typename PyReturnType, int fdefindex > - PyType* accessor ( PySelf* self ) { - string methodName = pyObjectMethods.getFullMethodName(fdefindex); - - trace << methodName << endl; - - ReturnType* value = NULL; - try { - CppType* cppThis = getCppObject( self ); - if (cppThis == NULL) return NULL; - - - } - } -#endif - - static PyObject* PyQuery_getMasterCell ( PyQuery *self ) { trace << "PyQuery.getMasterCell()" << endl; @@ -235,6 +144,54 @@ extern "C" { } + static PyObject* PyQuery_getInstance ( PyQuery *self ) { + trace << "PyQuery.getInstance()" << endl; + + Instance* instance = NULL; + + HTRY + METHOD_HEAD("PyQuery.getInstance()") + instance = query->getInstance(); + HCATCH + + return PyInstance_Link(instance); + } + + + static PyObject* PyQuery_getPath ( PyQuery *self ) + { + trace << "PyQuery_getPath ()" << endl; + + METHOD_HEAD( "PyQuery.getPath()" ) + + PyPath* pyPath = PyObject_NEW( PyPath, &PyTypePath ); + if (pyPath == NULL) return NULL; + + HTRY + pyPath->_object = new Path ( query->getPath() ); + HCATCH + + return (PyObject*)pyPath; + } + + + static PyObject* PyQuery_getTransformation ( PyQuery *self ) + { + trace << "PyQuery_getTransformation ()" << endl; + + METHOD_HEAD( "PyQuery.getTransformation()" ) + + PyTransformation* pyTransformation = PyObject_NEW( PyTransformation, &PyTypeTransformation ); + if (pyTransformation == NULL) return NULL; + + HTRY + pyTransformation->_object = new Transformation ( query->getTransformation() ); + HCATCH + + return (PyObject*)pyTransformation; + } + + static PyObject* PyQuery_setCell ( PyQuery* self, PyObject* args ) { trace << "PyQuery.setCell()" << endl; @@ -258,6 +215,24 @@ extern "C" { } + static PyObject* PyQuery_setFilter ( PyQuery* self, PyObject* args ) + { + trace << "PyQuery.setFilter()" << endl; + METHOD_HEAD("PyQuery.setFilter()") + + HTRY + int mask = 0; + if (PyArg_ParseTuple(args,"i:Query.setFilter()",&mask) ) { + query->setFilter( mask ); + } else { + PyErr_SetString ( ConstructorError, "Bad parameters given to Query.setFilter()." ); + return NULL; + } + HCATCH + Py_RETURN_NONE; + } + + static PyObject* PyQuery_setArea ( PyQuery* self, PyObject* args ) { trace << "PyQuery.setArea()" << endl; @@ -446,16 +421,14 @@ extern "C" { { trace << "PyQuery.new()" << endl; - Query* query = NULL; - PyQuery* pyQuery = NULL; + BaseQuery* query = NULL; + PyQuery* pyQuery = NULL; HTRY pyQuery = PyObject_NEW( PyQuery, &PyTypeQuery ); if (pyQuery == NULL) return NULL; query = new BaseQuery( pyQuery ); pyQuery->_object = query; - - cerr << "PyQuery_NEW(): " << (void*)pyQuery << endl; HCATCH return (PyObject*)pyQuery; @@ -464,7 +437,6 @@ extern "C" { int PyQuery_Init ( PyQuery* self, PyObject* args, PyObject* kwargs ) { - cerr << "PyQuery_Init(): " << (void*)self << endl; return 0; } @@ -478,8 +450,16 @@ extern "C" { PyMethodDef PyQuery_Methods[] = { { "getMasterCell" , (PyCFunction)PyQuery_getMasterCell , METH_NOARGS , "Returns the master Cell currently under exploration." } + , { "getInstance" , (PyCFunction)PyQuery_getInstance , METH_NOARGS + , "Returns the Instance currently under exploration." } + , { "getPath" , (PyCFunction)PyQuery_getPath , METH_NOARGS + , "Returns the Path to the Instance (inclusive) under exploration." } + , { "getTransformation" , (PyCFunction)PyQuery_getTransformation , METH_NOARGS + , "Returns the Transformation to the master Cell under exploration." } , { "setCell" , (PyCFunction)PyQuery_setCell , METH_VARARGS , "Set the cell upon which perform the query." } + , { "setFilter" , (PyCFunction)PyQuery_setFilter , METH_VARARGS + , "Set what classes of objects will be took into account." } , { "setArea" , (PyCFunction)PyQuery_setArea , METH_VARARGS , "Set the area into which perform the query." } , { "setTransformation" , (PyCFunction)PyQuery_setTransformation , METH_VARARGS @@ -494,9 +474,9 @@ extern "C" { , "Set the callback function for the Rubbers." } , { "setExtensionGoCallback", (PyCFunction)PyQuery_setExtensionGoCallback, METH_VARARGS , "Set the callback function for the ExtensionGos." } - , { "setMasterCellCallback" , (PyCFunction)PyQuery_setMasterCellCallback, METH_VARARGS + , { "setMasterCellCallback" , (PyCFunction)PyQuery_setMasterCellCallback , METH_VARARGS , "Set the callback function for the MasterCell." } - , { "doQuery" , (PyCFunction)PyQuery_doQuery , METH_NOARGS + , { "doQuery" , (PyCFunction)PyQuery_doQuery , METH_NOARGS , "Perform the actual Query walk." } , {NULL, NULL, 0, NULL} /* sentinel */ }; @@ -509,56 +489,6 @@ extern "C" { DirectDeleteMethod(PyQuery_DeAlloc,PyQuery) PyTypeObjectLinkPyTypeNewInit(Query) -#if WORK_IN_PROGRESS - DirectReprMethod(PyQuery_Repr, PyQuery, Query) - DirectStrMethod (PyQuery_Str, PyQuery, Query) - DirectCmpMethod (PyQuery_Cmp, IsPyQuery, PyQuery) - DirectHashMethod(PyQuery_Hash, PyQuery) - - - extern void PyQuery_LinkPyType () - { - trace << "PyQuery_LinkType()" << endl; - - PyTypeQuery.tp_dealloc = (destructor) PyQuery_DeAlloc; - PyTypeQuery.tp_compare = (cmpfunc) PyQuery_Cmp; - PyTypeQuery.tp_repr = (reprfunc) PyQuery_Repr; - PyTypeQuery.tp_str = (reprfunc) PyQuery_Str; - PyTypeQuery.tp_hash = (hashfunc) PyQuery_Hash; - PyTypeQuery.tp_new = (newfunc) PyQuery_NEW; - PyTypeQuery.tp_init = (initproc) PyQuery_Init; - //PyTypeQuery.tp_methods = PyQuery_Methods; - - if (not pyObjectMethods.size()) { - pyObjectMethods - ( "getMasterCell" , (PyCFunction)PyQuery_getMasterCell, METH_NOARGS - , "Returns the master Cell currently under exploration." ) - ( "setCell" , (PyCFunction)PyQuery_setCell, METH_VARARGS - , "Set the cell upon which perform the query." ) - ( "setArea" , (PyCFunction)PyQuery_setArea, METH_VARARGS - , "Set the area into which perform the query." ) - ( "setTransformation" , (PyCFunction)PyQuery_setTransformation, METH_VARARGS - , "Set the initial transformation applied to the query area." ) - ( "setBasicLayer" , (PyCFunction)PyQuery_setBasicLayer, METH_VARARGS - , "Set the BasicLayer on which perform the query." ) - ( "setGoCallback" , (PyCFunction)PyQuery_setGoCallback, METH_VARARGS - , "Set the callback function for the Gos." ) - ( "setMarkerCallback" , (PyCFunction)PyQuery_setMarkerCallback, METH_VARARGS - , "Set the callback function for the Markers." ) - ( "setRubberCallback" , (PyCFunction)PyQuery_setRubberCallback, METH_VARARGS - , "Set the callback function for the Rubbers." ) - ( "setExtensionGoCallback", (PyCFunction)PyQuery_setExtensionGoCallback, METH_VARARGS - , "Set the callback function for the ExtensionGos." ) - ( "setMasterCellCallback" , (PyCFunction)PyQuery_setMasterCellCallback, METH_VARARGS - , "Set the callback function for the MasterCell." ) - ( "doQuery" , (PyCFunction)PyQuery_doQuery, METH_NOARGS - , "Perform the actual Query walk." ); - } - - PyTypeQuery.tp_methods = pyObjectMethods.getMethods(); - } -#endif - #else // End of Python Module Code Part. diff --git a/hurricane/src/isobar/PyRegularLayer.cpp b/hurricane/src/isobar/PyRegularLayer.cpp index dec90c02..231db016 100644 --- a/hurricane/src/isobar/PyRegularLayer.cpp +++ b/hurricane/src/isobar/PyRegularLayer.cpp @@ -107,6 +107,7 @@ extern "C" { // Standart Attribute. + accessorLayerFromVoid(getBasicLayer ,PyRegularLayer,RegularLayer) updatorFromBasicLayer(setBasicLayer ,PyRegularLayer,RegularLayer) DBoDestroyAttribute (PyRegularLayer_destroy, PyRegularLayer) @@ -117,6 +118,8 @@ extern "C" { PyMethodDef PyRegularLayer_Methods[] = { { "create" , (PyCFunction)PyRegularLayer_create , METH_VARARGS|METH_STATIC , "Create a new RegularLayer." } + , { "getBasicLayer", (PyCFunction)PyRegularLayer_getBasicLayer, METH_NOARGS + , "Get the BasicLayer associated to this RegularLayer." } , { "setBasicLayer", (PyCFunction)PyRegularLayer_setBasicLayer, METH_VARARGS , "Associate a BasicLayer with this RegularLayer." } , { "destroy" , (PyCFunction)PyRegularLayer_destroy , METH_NOARGS diff --git a/hurricane/src/isobar/PyTechnology.cpp b/hurricane/src/isobar/PyTechnology.cpp index 7ba416d2..774da9ea 100644 --- a/hurricane/src/isobar/PyTechnology.cpp +++ b/hurricane/src/isobar/PyTechnology.cpp @@ -146,7 +146,7 @@ extern "C" { } HCATCH - return PyLayer_Link(layer); + return PyLayer_LinkDerived(layer); } diff --git a/hurricane/src/isobar/hurricane/isobar/PyDebugSession.h b/hurricane/src/isobar/hurricane/isobar/PyDebugSession.h index d37c277e..4b302a89 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyDebugSession.h +++ b/hurricane/src/isobar/hurricane/isobar/PyDebugSession.h @@ -43,8 +43,8 @@ namespace Isobar { #define IsPyDebugSession(v) ( (v)->ob_type == &PyTypeDebugSession ) -#define PYUPDATESESSION(v) ( (PyDebugSession*)(v) ) -#define PYUPDATESESSION_O(v) ( PY_UPDATE_SESSION(v)->_object ) +#define PYDEBUGSESSION(v) ( (PyDebugSession*)(v) ) +#define PYDEBUGSESSION_O(v) ( PY_UPDATE_SESSION(v)->_object ) } // extern "C". diff --git a/hurricane/src/isobar/hurricane/isobar/PyHurricane.h b/hurricane/src/isobar/hurricane/isobar/PyHurricane.h index 8e29f846..350f48c8 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyHurricane.h +++ b/hurricane/src/isobar/hurricane/isobar/PyHurricane.h @@ -120,6 +120,7 @@ extern "C" { #define NO_ARG "" #define BOX_ARG ":box" +#define INTV_ARG ":intv" #define CELL_ARG ":ent" #define POINT_ARG ":point" #define POINTS2_ARG ":point:point" @@ -324,6 +325,23 @@ extern "C" { } +# define accessorLayerFromVoid(FUNC_NAME,PY_SELF_TYPE,SELF_TYPE) \ + static PyObject* PY_SELF_TYPE##_##FUNC_NAME ( PY_SELF_TYPE* self ) \ + { \ + trace << #PY_SELF_TYPE "_" #FUNC_NAME "()" << endl; \ + \ + Layer* rlayer = NULL; \ + \ + HTRY \ + GENERIC_METHOD_HEAD(SELF_TYPE,cobject,#SELF_TYPE"."#FUNC_NAME"()") \ + rlayer = const_cast( dynamic_cast(cobject->FUNC_NAME()) ); \ + HCATCH \ + \ + if (rlayer == NULL) Py_RETURN_NONE; \ + return PyLayer_LinkDerived(rlayer); \ + } + + # define accessorAnyLayerFromName(FUNC_NAME,PY_SELF_TYPE,SELF_TYPE,LAYER_TYPE) \ static PyObject* PY_SELF_TYPE##_##FUNC_NAME ( PY_SELF_TYPE* self, PyObject* args ) \ { \ @@ -382,7 +400,7 @@ extern "C" { HCATCH \ \ if (rlayer == NULL) Py_RETURN_NONE; \ - return PyLayer_Link(rlayer); \ + return PyLayer_LinkDerived(rlayer); \ } @@ -414,7 +432,7 @@ extern "C" { HCATCH \ \ if (rlayer == NULL) Py_RETURN_NONE; \ - return PyLayer_Link(rlayer); \ + return PyLayer_LinkDerived(rlayer); \ } @@ -439,7 +457,7 @@ extern "C" { HCATCH \ \ if (rlayer == NULL) Py_RETURN_NONE; \ - return PyLayer_Link(rlayer); \ + return PyLayer_LinkDerived(rlayer); \ } diff --git a/hurricane/src/isobar/hurricane/isobar/PyInterval.h b/hurricane/src/isobar/hurricane/isobar/PyInterval.h new file mode 100644 index 00000000..788ef558 --- /dev/null +++ b/hurricane/src/isobar/hurricane/isobar/PyInterval.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +// +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2014-2014, All Rights Reserved +// +// +-----------------------------------------------------------------+ +// | C O R I O L I S | +// | I s o b a r - Hurricane / Python Interface | +// | | +// | Author : Jean-Paul CHAPUT | +// | E-mail : Jean-Paul.Chaput@lip6.fr | +// | =============================================================== | +// | C++ Header : "./hurricane/isobar/PyInterval.h" | +// +-----------------------------------------------------------------+ + + +#ifndef ISOBAR_PY_INTERVAL_H +#define ISOBAR_PY_INTERVAL_H + +#include "hurricane/isobar/PyHurricane.h" +#include "hurricane/Interval.h" + + +namespace Isobar { + + extern "C" { + +// ------------------------------------------------------------------- +// Python Object : "PyInterval". + + typedef struct { + PyObject_HEAD + Hurricane::Interval* _object; + } PyInterval; + + +// ------------------------------------------------------------------- +// Functions & Types exported to "PyHurricane.cpp". + + extern PyTypeObject PyTypeInterval; + extern PyMethodDef PyInterval_Methods[]; + + extern PyObject* PyInterval_Link ( Hurricane::Interval* object ); + extern void PyInterval_LinkPyType (); + + +#define IsPyInterval(v) ( (v)->ob_type == &PyTypeInterval ) +#define PYINTERVAL(v) ( (PyInterval*)(v) ) +#define PYINTERVAL_O(v) ( PYINTERVAL(v)->_object ) + + + } // extern "C". + +} // Isobar namespace. + +#endif // PY_INTERVAL_H diff --git a/hurricane/src/isobar/hurricane/isobar/PyLayer.h b/hurricane/src/isobar/hurricane/isobar/PyLayer.h index 82ea32e2..287bc871 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyLayer.h +++ b/hurricane/src/isobar/hurricane/isobar/PyLayer.h @@ -1,36 +1,8 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2006-2014, All Rights Reserved // -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -43,8 +15,8 @@ // +-----------------------------------------------------------------+ -# ifndef __PYLAYER__ -# define __PYLAYER__ +# ifndef ISOBAR_PYLAYER_H +# define ISOBAR_PYLAYER_H #include "hurricane/isobar/PyHurricane.h" #include "hurricane/Layer.h" @@ -71,6 +43,7 @@ extern "C" { extern PyMethodDef PyLayer_Methods[]; extern PyObject* PyLayer_Link ( Hurricane::Layer* object ); + extern PyObject* PyLayer_LinkDerived ( Hurricane::Layer* object ); extern void PyLayer_LinkPyType (); extern void PyLayer_postModuleInit (); @@ -83,4 +56,4 @@ extern "C" { } // Isobar namespace. -# endif +#endif // ISOBAR_PYLAYER_H diff --git a/hurricane/src/isobar/hurricane/isobar/PyQuery.h b/hurricane/src/isobar/hurricane/isobar/PyQuery.h index 1de6cbdb..46189a62 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyQuery.h +++ b/hurricane/src/isobar/hurricane/isobar/PyQuery.h @@ -1,36 +1,8 @@ - // -*- C++ -*- // -// This file is part of the Coriolis Project. -// Copyright (C) Laboratoire LIP6 - Departement ASIM -// Universite Pierre et Marie Curie +// This file is part of the Coriolis Software. +// Copyright (c) UPMC 2010-2014, All Rights Reserved // -// Main contributors : -// Christophe Alexandre -// Sophie Belloeil -// Hugo Clément -// Jean-Paul Chaput -// Damien Dupuis -// Christian Masson -// Marek Sroka -// -// The Coriolis Project is free software; you can redistribute it -// and/or modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 of -// the License, or (at your option) any later version. -// -// The Coriolis Project is distributed in the hope that it will be -// useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with the Coriolis Project; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -// USA -// -// License-Tag -// Authors-Tag // // +-----------------------------------------------------------------+ // | C O R I O L I S | @@ -54,128 +26,33 @@ namespace Isobar { using namespace Hurricane; -#if WORK_IN_PROGRESS - template< typename CppObject, int TableSize > - class MethodDefTable { - public: - MethodDefTable (); - PyMethodDef* getMethods (); - const PyMethodDef& operator[] ( size_t ); - MethodDefTable& addMethod ( const char* fname, PyCFunction, int flags, const char* fdoc ); - MethodDefTable& operator() ( const char* fname, PyCFunction, int flags, const char* fdoc ); - template< typename R, typename... Ps > - MethodDefTable& addMethod ( const char* fname, PyCFunction, int flags, const char* fdoc, R(CppObject::* mfp)(Ps...) ); - template< typename R, typename... Ps > - MethodDefTable& operator() ( const char* fname, PyCFunction, int flags, const char* fdoc, R(CppObject::* mfp)(Ps...) ); - inline size_t size () const; - private: - size_t _size; - PyMethodDef _pyMethods [TableSize]; - void* _cppMethods[TableSize]; - }; - - - template< typename CppObject, int TableSize > - size_t MethodDefTable::size () const - { return _size; } - - - template< typename CppObject, int TableSize > - MethodDefTable::MethodDefTable () - : _size (0) - //, _pyMethods(new PyMethodDef[TableSize+1]) - { - for ( size_t i=0 ; i - PyMethodDef* MethodDefTable::getMethods () - { return _pyMethods; } - - - template< typename CppObject, int TableSize > - const PyMethodDef& MethodDefTable::operator[] ( size_t i ) - { return _pyMethods[i]; } - - - template< typename CppObject, int TableSize > - MethodDefTable& MethodDefTable::addMethod ( const char* fname, PyCFunction fp, int flags, const char* fdoc ) - { - _pyMethods [_size].ml_name = fname; - _pyMethods [_size].ml_meth = fp; - _pyMethods [_size].ml_flags = flags; - _pyMethods [_size].ml_doc = fdoc; - _cppMethods[_size] = NULL; - ++_size; - - return *this; - } - - - template< typename CppObject, int TableSize > - template< typename R, typename... Ps > - MethodDefTable& MethodDefTable::addMethod - ( const char* fname, PyCFunction fp, int flags, const char* fdoc, R(CppObject::* mfp)(Ps...) ) - { - _pyMethods[_size].ml_name = fname; - _pyMethods[_size].ml_meth = fp; - _pyMethods[_size].ml_flags = flags; - _pyMethods[_size].ml_doc = fdoc; - _cppMethods[_size] = (void*)mfp; - ++_size; - - return *this; - } - - - template< typename CppObject, int TableSize > - MethodDefTable& MethodDefTable::operator() ( const char* fname, PyCFunction fp, int flags, const char* fdoc ) - { return addMethod( fname, fp, flags, fdoc ); } - - - template< typename CppObject, int TableSize > - template< typename R, typename... Ps > - MethodDefTable& MethodDefTable::operator() - ( const char* fname, PyCFunction fp, int flags, const char* fdoc, R(CppObject::* mfp)(Ps...) ) - { return addMethod( fname, fp, flags, fdoc, mfp ); } -#endif - - -extern "C" { - + extern "C" { // ------------------------------------------------------------------- // Python Object : "PyQuery". - typedef struct { - PyObject_HEAD - Query* _object; - } PyQuery; + typedef struct { + PyObject_HEAD + Query* _object; + } PyQuery; // ------------------------------------------------------------------- // Functions & Types exported to "PyHurricane.ccp". - extern PyTypeObject PyTypeQuery; - extern PyMethodDef PyQuery_Methods[]; + extern PyTypeObject PyTypeQuery; + extern PyMethodDef PyQuery_Methods[]; - extern PyObject* PyQuery_Link ( Hurricane::Query* object ); - extern void PyQuery_LinkPyType (); - extern void PyQuery_postModuleInit (); + extern PyObject* PyQuery_Link ( Query* object ); + extern void PyQuery_LinkPyType (); + extern void PyQuery_postModuleInit (); #define IsPyQuery(v) ( (v)->ob_type == &PyTypeQuery ) #define PYQUERY(v) ( (PyQuery*)(v) ) #define PYQUERY_O(v) ( PYQUERY(v)->_object ) -} // extern "C". + } // extern "C". } // Isobar namespace. diff --git a/hurricane/src/isobar/hurricane/isobar/PyUpdateSession.h b/hurricane/src/isobar/hurricane/isobar/PyUpdateSession.h index 6c34f851..6fecf64e 100644 --- a/hurricane/src/isobar/hurricane/isobar/PyUpdateSession.h +++ b/hurricane/src/isobar/hurricane/isobar/PyUpdateSession.h @@ -1,30 +1,21 @@ - // -*- C++ -*- // // This file is part of the Coriolis Software. -// Copyright (c) UPMC/LIP6 2010-2010, All Rights Reserved +// Copyright (c) UPMC/LIP6 2010-2014, All Rights Reserved // -// x-----------------------------------------------------------------x -// | | +// +-----------------------------------------------------------------+ // | C O R I O L I S | // | I s o b a r - Hurricane / Python Interface | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | -// | C++ Header : "./PyUpdateSession.h" | -// | *************************************************************** | -// | U p d a t e s | -// | | -// x-----------------------------------------------------------------x +// | C++ Header : "./hurrican/isobar/PyUpdateSession.h" | +// +-----------------------------------------------------------------+ - - - -# ifndef __PY_UPDATE_SESSION__ -# define __PY_UPDATE_SESSION__ - +#ifndef ISOBAR_PY_UPDATE_SESSION +#define ISOBAR_PY_UPDATE_SESSION #include "hurricane/isobar/PyHurricane.h" #include "hurricane/UpdateSession.h" @@ -32,26 +23,23 @@ namespace Isobar { - -extern "C" { + extern "C" { // ------------------------------------------------------------------- // Python Object : "PyUpdateSession". - typedef struct { - PyObject_HEAD - } PyUpdateSession; - - + typedef struct { + PyObject_HEAD + } PyUpdateSession; // ------------------------------------------------------------------- // Functions & Types exported to "PyHurricane.cpp". - extern PyTypeObject PyTypeUpdateSession; - extern PyMethodDef PyUpdateSession_Methods[]; + extern PyTypeObject PyTypeUpdateSession; + extern PyMethodDef PyUpdateSession_Methods[]; - extern void PyUpdateSession_LinkPyType (); + extern void PyUpdateSession_LinkPyType (); #define IsPyUpdateSession(v) ( (v)->ob_type == &PyTypeUpdateSession ) @@ -59,13 +47,8 @@ extern "C" { #define PYUPDATESESSION_O(v) ( PY_UPDATE_SESSION(v)->_object ) -} // End of extern "C". + } // extern "C". +} // Isobar namespace. - -} // End of Isobar namespace. - - - - -# endif +#endif diff --git a/unicorn/src/init/unicornInit.py b/unicorn/src/init/unicornInit.py index c16413ac..8812ce4c 100644 --- a/unicorn/src/init/unicornInit.py +++ b/unicorn/src/init/unicornInit.py @@ -1,6 +1,21 @@ #!/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 | +# | U n i c o r n - M a i n G U I | +# | | +# | Author : Jean-Paul CHAPUT | +# | E-mail : Jean-Paul.Chaput@asim.lip6.fr | +# | =============================================================== | +# | Python : "./init/unicornInit.py" | +# +-----------------------------------------------------------------+ + try: + import traceback import sys import os.path from helpers import ErrorMessage @@ -49,16 +64,24 @@ def unicornConfigure ( **kw ): editor.addMenu( 'plugins', 'Plu&gins', Viewer.CellViewer.TopMenu ) for pluginFile in os.listdir( pluginsDir ): + if pluginFile == "__init__.py": continue if not pluginFile.endswith('.py'): continue - moduleName = os.path.basename(pluginFile)[:-3] - module = __import__( moduleName, globals(), locals(), moduleName ) - if not module.__dict__.has_key('unicornHook'): - print WarningMessage( 'Module <%s> do not provides the unicornHook() method, skipped.' \ - % moduleName ) - continue + try: + module = __import__( moduleName, globals(), locals(), moduleName ) - module.__dict__['unicornHook']( editor ) + if not module.__dict__.has_key('unicornHook'): + print WarningMessage( 'Plugin <%s> do not provides the unicornHook() method, skipped.' \ + % moduleName ) + continue + + module.__dict__['unicornHook']( **kw ) + except ErrorMessage, e: + print e + except Exception, e: + print ErrorMessage( 3, 'Plugin <%s> cannot be loaded, see message below:' % moduleName ) + print e + traceback.print_tb(sys.exc_info()[2]) return