From 82dc58bf8e88950d16d333a12ea6ad6ef6a75288 Mon Sep 17 00:00:00 2001 From: Jean-Paul Chaput Date: Fri, 10 May 2019 11:58:05 +0200 Subject: [PATCH] Redesign of I/O pads and Corona support to mix real and symbolic. * Bug: In CRL/etc/symbolic/cmos/plugins.conf, rails dimensions are no longer expressed directly in lambda. Must be created using helper.l(). * Change: In CRL::ApParser, slightly more smart management of Pin width. Must normalize Pin behavior between Alliance & Hurricane as in Alliance they have only one dimension. * Change: In CRL::LefImport, if a net name end with "!", assume it's a global one. Have to check this naming convention. * Change: In Anabatic::NetBuilderHV::_do_1G_1PinM3() & _do_1G_1PinM2() now implemented. Needed for the corona routing support. * Change: In AnabaticEngine::setupPreRouted(), exclude segments outside the abutment box. * Change: In KatanaEngine::PowerRails, remove the I/O pad support as now we route only inside the Corona. So only one vdd/vss/ck are supported. * New: In cumulus/plugins/ChipPlugin.py, complete rewrite of the chip support: * Uncouple pad I/O ring whith real cells (foundry) from a symbolic core. A new intermediate level "corona" is introduced to handle the real/symbolic transition. * Ability to explicitly setup position of the pads on the chip side in case of uneven distribution. * Enable clock tree to be build with 3 metal only (M2 to M4) instead of (M2 to M5). --- anabatic/src/NetBuilderHV.cpp | 34 +- anabatic/src/PreRouteds.cpp | 18 +- anabatic/src/anabatic/NetBuilderHV.h | 1 + crlcore/etc/symbolic/cmos/plugins.conf | 11 +- crlcore/src/ccore/alliance/ap/ApDriver.cpp | 17 +- crlcore/src/ccore/ispd05/Ispd05Bookshelf.cpp | 11 - crlcore/src/ccore/lefdef/LefImport.cpp | 2 + cumulus/src/CMakeLists.txt | 48 +- cumulus/src/plugins/ChipPlace.py | 171 +-- cumulus/src/plugins/ChipRoute.py | 89 ++ cumulus/src/plugins/ClockTreePlugin.py | 28 +- cumulus/src/plugins/__init__.py | 10 + cumulus/src/plugins/chip/BlockCorona.py | 218 +-- cumulus/src/plugins/chip/BlockPower.py | 70 +- cumulus/src/plugins/chip/Chip.py | 205 +++ cumulus/src/plugins/chip/Configuration.py | 1105 +++++++++------ cumulus/src/plugins/chip/PadsCorona.py | 1308 ++++++++++++++---- cumulus/src/plugins/chip/__init__.py | 23 +- cumulus/src/plugins/clocktree/ClockTree.py | 109 +- katana/src/NegociateWindow.cpp | 1 + katana/src/PowerRails.cpp | 312 ++--- katana/src/PreProcess.cpp | 10 +- katana/src/PreRouteds.cpp | 6 - 23 files changed, 2426 insertions(+), 1381 deletions(-) create mode 100644 cumulus/src/plugins/ChipRoute.py create mode 100644 cumulus/src/plugins/chip/Chip.py diff --git a/anabatic/src/NetBuilderHV.cpp b/anabatic/src/NetBuilderHV.cpp index a8365ea4..f6dddcd5 100644 --- a/anabatic/src/NetBuilderHV.cpp +++ b/anabatic/src/NetBuilderHV.cpp @@ -416,9 +416,37 @@ namespace Anabatic { { cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl; - AutoContact* rpContact = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags ); - AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); - AutoSegment::create( rpContact, turn1, Flags::Vertical ); + AutoContact* rpContactSource = NULL; + AutoContact* rpContactTarget = NULL; + + doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpContactSource, rpContactTarget, NoFlags ); + + AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpContactSource, turn1, Flags::Horizontal ); + + if (east() or west()) { + AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( turn1, turn2, Flags::Vertical ); + turn1 = turn2; + } + setBothCornerContacts( turn1 ); + + cdebug_tabw(145,-1); + return true; + } + + + bool NetBuilderHV::_do_1G_1PinM3 () + { + cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM3() [Managed Configuration - Optimized] " << getTopology() << endl; + + AutoContact* rpContactSource = NULL; + AutoContact* rpContactTarget = NULL; + + doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpContactSource, rpContactTarget, NoFlags ); + + AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); + AutoSegment::create( rpContactSource, turn1, Flags::Vertical ); if (north() or south()) { AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); diff --git a/anabatic/src/PreRouteds.cpp b/anabatic/src/PreRouteds.cpp index 2168fab7..bc90ead1 100644 --- a/anabatic/src/PreRouteds.cpp +++ b/anabatic/src/PreRouteds.cpp @@ -73,6 +73,8 @@ namespace Anabatic { openSession(); size_t toBeRouteds = 0; + Box ab = getCell()->getAbutmentBox(); + ab.inflate( -1 ); for ( Net* net : getCell()->getNets() ) { if (net == _blockageNet) continue; @@ -96,6 +98,9 @@ namespace Anabatic { Horizontal* horizontal = dynamic_cast(component); if (horizontal) { + if ( not ab.contains(horizontal->getSourcePosition()) + and not ab.contains(horizontal->getTargetPosition()) ) continue; + segments.push_back( horizontal ); isPreRouted = true; if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer())) @@ -103,6 +108,9 @@ namespace Anabatic { } else { Vertical* vertical = dynamic_cast(component); if (vertical) { + if ( not ab.contains(vertical->getSourcePosition()) + and not ab.contains(vertical->getTargetPosition()) ) continue; + isPreRouted = true; segments.push_back( vertical ); if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer())) @@ -110,6 +118,8 @@ namespace Anabatic { } else { Contact* contact = dynamic_cast(component); if (contact) { + if (not ab.contains(contact->getCenter())) continue; + isPreRouted = true; contacts.push_back( contact ); if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer())) @@ -165,10 +175,10 @@ namespace Anabatic { AutoContact::createFrom( icontact ); } - for ( auto isegment : segments ) { - AutoContact* source = Session::lookup( dynamic_cast( isegment->getSource() )); - AutoContact* target = Session::lookup( dynamic_cast( isegment->getTarget() )); - AutoSegment* autoSegment = AutoSegment::create( source, target, isegment ); + for ( auto segment : segments ) { + AutoContact* source = Session::lookup( dynamic_cast( segment->getSource() )); + AutoContact* target = Session::lookup( dynamic_cast( segment->getTarget() )); + AutoSegment* autoSegment = AutoSegment::create( source, target, segment ); autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet ); } } diff --git a/anabatic/src/anabatic/NetBuilderHV.h b/anabatic/src/anabatic/NetBuilderHV.h index aea30466..5aba4779 100644 --- a/anabatic/src/anabatic/NetBuilderHV.h +++ b/anabatic/src/anabatic/NetBuilderHV.h @@ -39,6 +39,7 @@ namespace Anabatic { virtual bool _do_2G_1M1 (); virtual bool _do_xG_1Pad (); virtual bool _do_1G_1PinM2 (); + virtual bool _do_1G_1PinM3 (); virtual bool _do_xG_1M1 (); virtual bool _do_xG_1M1_1M2 (); virtual bool _do_xG_xM1_xM3 (); diff --git a/crlcore/etc/symbolic/cmos/plugins.conf b/crlcore/etc/symbolic/cmos/plugins.conf index 99609a4f..497dd405 100644 --- a/crlcore/etc/symbolic/cmos/plugins.conf +++ b/crlcore/etc/symbolic/cmos/plugins.conf @@ -1,6 +1,7 @@ # -*- Mode:Python; explicit-buffer-name: "plugins.conf" -*- import helpers +from helpers import l, u, n # Contains the layout (shared by all technologies). #execfile( helpers.sysConfDir+'/common/plugins.conf' ) @@ -8,11 +9,11 @@ import helpers # Parameters for chip plugin. parametersTable = \ - ( ("chip.block.rails.count" , TypeInt , 5 ) - , ("chip.block.rails.hWidth" , TypeInt , 12 ) - , ("chip.block.rails.vWidth" , TypeInt , 12 ) - , ("chip.block.rails.hSpacing" , TypeInt , 6 ) - , ("chip.block.rails.vSpacing" , TypeInt , 6 ) + ( ("chip.block.rails.count" , TypeInt , 5 ) + , ("chip.block.rails.hWidth" , TypeInt , l(12) ) + , ("chip.block.rails.vWidth" , TypeInt , l(12) ) + , ("chip.block.rails.hSpacing" , TypeInt , l(6) ) + , ("chip.block.rails.vSpacing" , TypeInt , l(6) ) , ('chip.pad.pck' , TypeString, 'pck_px') , ('chip.pad.pvddick' , TypeString, 'pvddick_px') , ('chip.pad.pvssick' , TypeString, 'pvssick_px') diff --git a/crlcore/src/ccore/alliance/ap/ApDriver.cpp b/crlcore/src/ccore/alliance/ap/ApDriver.cpp index afa06326..467def15 100644 --- a/crlcore/src/ccore/alliance/ap/ApDriver.cpp +++ b/crlcore/src/ccore/alliance/ap/ApDriver.cpp @@ -336,12 +336,21 @@ void DumpPins(ofstream &ccell, Cell* cell) } indexesSet.insert(index); if (pin->getWidth() != pin->getHeight()) - throw Warning(getString(pin->getName()) + " of " - + getString(net->getName()) - + " will be incompletely saved ... : AP format is only able to save square pins ..."); + throw Warning( "CRL::ApParser(): Pin \"" + getString(pin->getName()) + "\" of \"" + + getString(net->getName()) + + "\", AP format support only square shapes."); + + DbU::Unit width = 0; + switch ( pin->getAccessDirection() ) { + case Pin::AccessDirection::NORTH: + case Pin::AccessDirection::SOUTH: width = pin->getWidth(); break; + case Pin::AccessDirection::EAST: + case Pin::AccessDirection::WEST: width = pin->getHeight(); break; + } + ccell << "C " << toMBKlambda(pin->getX()) << "," << toMBKlambda(pin->getY()) - << "," << toMBKlambda(pin->getWidth()) + << "," << toMBKlambda(width) << "," << toMBKName(pinName) << "," << index << ","; diff --git a/crlcore/src/ccore/ispd05/Ispd05Bookshelf.cpp b/crlcore/src/ccore/ispd05/Ispd05Bookshelf.cpp index 214fe60f..82f039b9 100644 --- a/crlcore/src/ccore/ispd05/Ispd05Bookshelf.cpp +++ b/crlcore/src/ccore/ispd05/Ispd05Bookshelf.cpp @@ -154,7 +154,6 @@ namespace CRL { AllianceFramework* af = AllianceFramework::get(); pitch = af->getCellGauge()->getPitch(); - size_t count = 0; UpdateSession::open (); unique_ptr circuit ( Bookshelf::Circuit::parse( benchmark @@ -173,11 +172,6 @@ namespace CRL { for ( auto net : circuit->getNets() ) { dots.dot(); Net::create ( cell, net->getName() ); - - if (++count % 1000) { - UpdateSession::close (); - UpdateSession::open (); - } } dots.finish( Dots::Reset|Dots::FirstDot ); @@ -202,11 +196,6 @@ namespace CRL { Net* masterNet = master->getNet( netName ); instance->getPlug( masterNet )->setNet( cell->getNet(netName) ); } - - if (++count % 1000) { - UpdateSession::close (); - UpdateSession::open (); - } } dots.finish( Dots::Reset|Dots::FirstDot ); diff --git a/crlcore/src/ccore/lefdef/LefImport.cpp b/crlcore/src/ccore/lefdef/LefImport.cpp index 81bdc09a..e9cf6257 100644 --- a/crlcore/src/ccore/lefdef/LefImport.cpp +++ b/crlcore/src/ccore/lefdef/LefImport.cpp @@ -522,6 +522,8 @@ namespace { Net* net = Net::create( parser->getCell(), pin->name() ); net->setExternal( true ); + if (pin->name()[ strlen(pin->name())-1 ] == '!') net->setGlobal( true ); + if (pin->hasDirection()) { string lefDir = pin->direction(); boost::to_upper( lefDir ); diff --git a/cumulus/src/CMakeLists.txt b/cumulus/src/CMakeLists.txt index 76c65e31..58d502f1 100644 --- a/cumulus/src/CMakeLists.txt +++ b/cumulus/src/CMakeLists.txt @@ -1,27 +1,29 @@ # -*- explicit-buffer-name: "CMakeLists.txt" -*- - set ( pySources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py - ${CMAKE_CURRENT_SOURCE_DIR}/ref.py - ${CMAKE_CURRENT_SOURCE_DIR}/Alliance.py - ) - set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipPlugin.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTreePlugin.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePlugin.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePluginAll.py - ) - set ( pyPluginCT ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/__init__.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/RSMT.py - ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/ClockTree.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 + set ( pySources ${CMAKE_CURRENT_SOURCE_DIR}/placeandroute.py + ${CMAKE_CURRENT_SOURCE_DIR}/ref.py + ${CMAKE_CURRENT_SOURCE_DIR}/Alliance.py + ) + set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipPlace.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipRoute.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/ClockTreePlugin.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePlugin.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePluginAll.py + ) + set ( pyPluginCT ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/RSMT.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/ClockTree.py + ) + set ( pyPluginChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/Configuration.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/Chip.py ) - install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) - install ( FILES ${pyPlugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) - install ( FILES ${pyPluginCT} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/clocktree ) - install ( FILES ${pyPluginChip} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/chip ) + install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) + install ( FILES ${pyPlugins} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins ) + install ( FILES ${pyPluginCT} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/clocktree ) + install ( FILES ${pyPluginChip} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus/plugins/chip ) diff --git a/cumulus/src/plugins/ChipPlace.py b/cumulus/src/plugins/ChipPlace.py index d0f04a18..72b264b0 100644 --- a/cumulus/src/plugins/ChipPlace.py +++ b/cumulus/src/plugins/ChipPlace.py @@ -10,56 +10,18 @@ # | Author : Jean-Paul CHAPUT | # | E-mail : Jean-Paul.Chaput@asim.lip6.fr | # | =============================================================== | -# | Python : "./plugins/ChipPlugin.py" | +# | Python : "./plugins/ChipPlace.py" | # +-----------------------------------------------------------------+ try: import sys import traceback - import os.path - import optparse - import math - import cProfile - import pstats - 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 import helpers from helpers import ErrorMessage from helpers import WarningMessage - #import Nimbus - #import Metis - #import Mauka - import Etesian - import Katabatic - import Kite - import Unicorn import plugins - import clocktree.ClockTree - import chip.Configuration - import chip.BlockPower - import chip.BlockCorona - import chip.PadsCorona + import chip.Chip except ImportError, e: serror = str(e) if serror.startswith('No module named'): @@ -79,112 +41,13 @@ except Exception, e: sys.exit(2) -# -------------------------------------------------------------------- -# Plugin working part. - - -class PlaceCore ( chip.Configuration.ChipConfWrapper ): - - def __init__ ( self, conf ): - chip.Configuration.ChipConfWrapper.__init__( self, conf.gaugeConf, conf.chipConf ) - 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 - x = x - (x % self.gaugeConf.getSliceHeight()) - y = y - (y % self.gaugeConf.getSliceHeight()) - 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 - - coreCell = self.cores[0].getMasterCell() - - checkUnplaced = plugins.CheckUnplaced( coreCell, plugins.NoFlags ) - if not checkUnplaced.check(): return - - ckCore = None - for plug in self.cko.getPlugs(): - if plug.getInstance() == self.cores[0]: - ckCore = plug.getMasterNet() - if not ckCore: - print WarningMessage( 'Core <%s> is not connected to chip clock.' - % self.cores[0].getName() ) - - if self.useClockTree and ckCore: - ht = clocktree.ClockTree.HTree.create( self, coreCell, ckCore, coreCell.getAbutmentBox() ) - ht.addCloned( self.cell ) - if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian': - mauka = Mauka.MaukaEngine.create( coreCell ) - mauka.run() - mauka.destroy() - else: - etesian = Etesian.EtesianEngine.create( coreCell ) - etesian.setViewer( self.viewer ) - etesian.place() - etesian.destroy() - - #profile = cProfile.Profile() - #profile.enable() - ht.connectLeaf() - #ht.prune() - ht.route() - ht.save( self.cell ) - #profile.disable() - - #stats = pstats.Stats( profile, stream=sys.stderr ) - #stats.strip_dirs() - #stats.sort_stats( 'cumtime' ) - #stats.print_stats() - else: - if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian': - mauka = Mauka.MaukaEngine.create( coreCell ) - mauka.run() - mauka.destroy() - else: - etesian = Etesian.EtesianEngine.create( coreCell ) - etesian.place() - etesian.destroy() - return - - - - # -------------------------------------------------------------------- # Plugin hook functions, unicornHook:menus, ScritMain:call def unicornHook ( **kw ): kw['beforeAction'] = 'placeAndRoute.stepByStep' + plugins.kwAddMenu ( 'placeAndRoute', 'P&&R', **kw ) plugins.kwUnicornHook( 'placeAndRoute.placeChip' , 'PLace Chip' , 'Place a Complete Chip (pads && core)' @@ -203,31 +66,11 @@ def ScriptMain ( **kw ): cell, editor = plugins.kwParseMain( **kw ) conf = chip.Configuration.loadConfiguration( cell, editor ) - if not conf.isValid(): return + if not conf.validated: return False - padsCorona = chip.PadsCorona.Corona( conf ) - if not padsCorona.validate(): return - - padsCorona.doLayout() - placeCore = PlaceCore( conf ) - placeCore.validate() - placeCore.doFloorplan() - if editor: editor.fit() - - placeCore.doPlacement() - if editor: editor.fit() - - corePower = chip.BlockPower.Block( conf ) - corePower.connectPower() - corePower.connectClock() - corePower.doLayout() - if editor: editor.fit() - - coreCorona = chip.BlockCorona.Corona( corePower ) - coreCorona.connectPads( padsCorona ) - coreCorona.connectBlock() - coreCorona.doLayout() - if editor: editor.fit() + placeChip = chip.Chip.PlaceRoute( conf ) + placeChip.doChipPlacement() + return placeChip.validated except ErrorMessage, e: print e; errorCode = e.code diff --git a/cumulus/src/plugins/ChipRoute.py b/cumulus/src/plugins/ChipRoute.py new file mode 100644 index 00000000..84e4cbf9 --- /dev/null +++ b/cumulus/src/plugins/ChipRoute.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2014-2018, 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/ChipRoute.py" | +# +-----------------------------------------------------------------+ + + +try: + import sys + import traceback + import Viewer + import helpers + from helpers import ErrorMessage + from helpers import WarningMessage + import plugins + import chip.Chip +except ImportError, e: + serror = str(e) + if serror.startswith('No module named'): + module = serror.split()[-1] + print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module + print ' Please check the integrity of the package.' + if str(e).find('cannot open shared object file'): + library = serror.split(':')[0] + print '[ERROR] The <%s> shared library cannot be loaded.' % library + print ' Under RHEL 6, you must be under devtoolset-2.' + print ' (scl enable devtoolset-2 bash)' + 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 hook functions, unicornHook:menus, ScritMain:call + +def unicornHook ( **kw ): + kw['beforeAction'] = 'placeAndRoute.stepByStep' + + plugins.kwAddMenu ( 'placeAndRoute', 'P&&R', **kw ) + plugins.kwUnicornHook( 'placeAndRoute.placeRouteChip' + , 'PLace && Route Chip' + , 'Place & route a Complete Chip (pads && core)' + , sys.modules[__name__].__file__ + , **kw + ) + return + + +def ScriptMain ( **kw ): + rvalue = True + try: + helpers.staticInitialization( quiet=True ) + #helpers.setTraceLevel( 550 ) + + cell, editor = plugins.kwParseMain( **kw ) + conf = chip.Configuration.loadConfiguration( cell, editor ) + if not conf.validated: return False + + prChip = chip.Chip.PlaceRoute( conf ) + prChip.doChipPlacement() + prChip.doChipRouting() + return prChip.validated + + except ErrorMessage, e: + print e; errorCode = e.code + if locals().has_key('editor') and editor \ + and locals().has_key('cell' ) and cell: editor.fit() + rvalue = False + except Exception, e: + print '\n\n', e; errorCode = 1 + traceback.print_tb(sys.exc_info()[2]) + rvalue = False + + sys.stdout.flush() + sys.stderr.flush() + + return rvalue diff --git a/cumulus/src/plugins/ClockTreePlugin.py b/cumulus/src/plugins/ClockTreePlugin.py index 60bb8d38..488109be 100755 --- a/cumulus/src/plugins/ClockTreePlugin.py +++ b/cumulus/src/plugins/ClockTreePlugin.py @@ -27,7 +27,6 @@ try: import helpers from helpers import trace from helpers import ErrorMessage - #import Mauka import Etesian import Unicorn import plugins @@ -56,8 +55,9 @@ except Exception, e: # Plugin hook functions, unicornHook:menus, ScritMain:call def unicornHook ( **kw ): - kw['beforeAction'] = 'placeAndRoute.placeChip' + kw['beforeAction'] = 'beta.placeAndRoute.placeChip' + plugins.kwAddMenu ( 'placeAndRoute', 'P&&R', **kw ) plugins.kwUnicornHook( 'placeAndRoute.clockTree' , 'Place Block && Clock Tree' , 'Place a block with a buffered H-Tree for the clock' @@ -93,38 +93,26 @@ def ScriptMain ( **kw ): if cell == None: raise ErrorMessage( 3, 'ClockTree: No cell loaded yet.' ) - framework = CRL.AllianceFramework.get() - cellGauge = framework.getCellGauge() + conf = chip.Configuration.ChipConf( {}, cell, editor ) if cell.getAbutmentBox().isEmpty(): spaceMargin = Cfg.getParamPercentage('etesian.spaceMargin').asPercentage() / 100.0 + 0.02 aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0 - clocktree.ClockTree.computeAbutmentBox( cell, spaceMargin, aspectRatio, cellGauge ) + clocktree.ClockTree.computeAbutmentBox( cell, spaceMargin, aspectRatio, conf.cellGauge ) if editor: editor.fit() - ht = clocktree.ClockTree.HTree.create( chip.Configuration.GaugeConfWrapper(chip.Configuration.GaugeConf()) - , cell, None, cell.getAbutmentBox() ) + ht = clocktree.ClockTree.HTree.create( conf, cell, None, cell.getAbutmentBox() ) if editor: editor.refresh() - if Cfg.getParamString('clockTree.placerEngine').asString() != 'Etesian': - mauka = Mauka.MaukaEngine.create( cell ) - mauka.run() - mauka.destroy() - else: - etesian = Etesian.EtesianEngine.create( cell ) - etesian.place() - etesian.destroy() + etesian = Etesian.EtesianEngine.create( cell ) + etesian.place() + etesian.destroy() ht.connectLeaf() #ht.prune() ht.route() ht.save( cell ) - #showNet( cell, 'ck_htree_bl_bl_bl' ) - #showNet( cell, 'ck_htree_bl_bl_br' ) - #showNet( cell, 'ck_htree_bl_bl_tl' ) - #showNet( cell, 'ck_htree_bl_bl_tr' ) - except ErrorMessage, e: print e; errorCode = e.code except Exception, e: diff --git a/cumulus/src/plugins/__init__.py b/cumulus/src/plugins/__init__.py index 0906568e..bf81502a 100644 --- a/cumulus/src/plugins/__init__.py +++ b/cumulus/src/plugins/__init__.py @@ -21,6 +21,7 @@ from Hurricane import Contact from Hurricane import Path from Hurricane import Occurrence from Hurricane import Instance +import Viewer import CRL from CRL import RoutingLayerGauge @@ -47,6 +48,15 @@ def kwParseMain ( **kw ): return cell, editor +def kwAddMenu ( menuPath, menuName, **kw ): + editor = kw['editor'] + if menuPath.find('.') >= 0: flags = Viewer.CellViewer.NoFlags + else: flags = Viewer.CellViewer.TopMenu + if not editor.hasMenu(menuPath): + editor.addMenu( menuPath, menuName, flags ) + return + + def kwUnicornHook ( menuPath, menuName, menuTip, moduleFile, **kw ): editor = kw['editor'] if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'): diff --git a/cumulus/src/plugins/chip/BlockCorona.py b/cumulus/src/plugins/chip/BlockCorona.py index 5308a66c..e4f12465 100644 --- a/cumulus/src/plugins/chip/BlockCorona.py +++ b/cumulus/src/plugins/chip/BlockCorona.py @@ -131,7 +131,11 @@ class HorizontalRail ( Rail ): , self.side.hRailWidth - DbU.fromLambda(1.0) ) , contact ] - #print ' ADD contact @ [%d %d]' % (DbU.toLambda(contact.getX()), DbU.toLambda(self.axis)) + trace( 550, '\tADD "%s" contact "%s" @ [%d %d]\n' + % ( contact.getNet().getName() + , contact.getLayer().getName() + , DbU.toLambda(contact.getX()) + , DbU.toLambda(self.axis)) ) self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) ) return True @@ -144,6 +148,7 @@ class HorizontalRail ( Rail ): for via in self.vias.values(): if via[1].getNet() != via[2].getNet(): continue + via[1].mergeDepth( self.side.getLayerDepth(self.side.getVLayer()) ) via[1].doLayout() #print ' Connect:', via[2], via[1].getVia( via[2].getLayer() ) Vertical.create( via[1].getVia( via[2].getLayer() ) @@ -152,9 +157,12 @@ class HorizontalRail ( Rail ): , via[2].getX() , via[2].getWidth() ) + #print via[1]._vias, '[%d %d]' % (via[1]._bottomDepth,via[1]._topDepth) + #print via[1], self.side.getVLayer(), via[1].getVia( self.side.getVLayer() ) railVias.append( via[1].getVia( self.side.getVLayer()) ) - railVias.sort( key=methodcaller('getY') ) + #print railVias + railVias.sort( key=methodcaller('getX') ) for i in range(1,len(railVias)): Horizontal.create( railVias[i-1] @@ -273,84 +281,85 @@ class VerticalRail ( Rail ): class Side ( object ): def __init__ ( self, corona ): - self._corona = corona + self.corona = corona return @property - def railsNb ( self ): return self._corona._railsNb + def railsNb ( self ): return self.corona.railsNb @property - def innerBb ( self ): return self._corona._innerBb + def innerBb ( self ): return self.corona.innerBb @property - def hRailWidth ( self ): return self._corona._hRailWidth + def hRailWidth ( self ): return self.corona.hRailWidth @property - def hRailSpace ( self ): return self._corona._hRailSpace + def hRailSpace ( self ): return self.corona.hRailSpace @property - def vRailWidth ( self ): return self._corona._vRailWidth + def vRailWidth ( self ): return self.corona.vRailWidth @property - def vRailSpace ( self ): return self._corona._vRailSpace + def vRailSpace ( self ): return self.corona.vRailSpace @property - def corners ( self ): return self._corona._corners + def corners ( self ): return self.corona.corners @property - def horizontalDepth ( self ): return self._corona.horizontalDepth + def horizontalDepth ( self ): return self.corona.horizontalDepth @property - def verticalDepth ( self ): return self._corona.verticalDepth + def verticalDepth ( self ): return self.corona.verticalDepth @property - def blockageNet ( self ): return self._corona.blockageNet + def blockageNet ( self ): return self.corona.blockageNet - 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 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] + 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)] + 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: + for rail in self.rails: rail.connect( terminal[1] ) return def connectPads ( self, padSide ): - for terminal in padSide._powerContacts: + for contact in padSide.pins: + if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue #print ' Connect to [-%i] @%d' % (0, DbU.toLambda(self.getOuterRail(0).axis)) - self.getOuterRail( 0 ).connect( terminal ) + self.getOuterRail( 0 ).connect( contact ) - halfRails = (len(self._rails)-1)/2 + halfRails = (len(self.rails)-1)/2 trace( 550, 'halfRails:%i' % halfRails ) - for terminal in padSide._powerContacts: - trace( 550, ',+', '\tConnect pad terminal %s\n' % terminal ) + for contact in padSide.pins: + if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue + trace( 550, ',+', '\tConnect pad contact %s\n' % contact ) for i in range(halfRails): trace( 550, '\tConnect to [-%i] @%d\n' % (i+1, DbU.toLambda(self.getOuterRail(i+1).axis)) ) - self.getOuterRail(i+1).connect( terminal ) + self.getOuterRail(i+1).connect( contact ) trace( 550, '-' ) return def doLayout ( self ): - for rail in self._rails: rail.doLayout() + for rail in self.rails: rail.doLayout() return class HorizontalSide ( Side ): def __init__ ( self, corona ): - #print 'HorizontalSide.__init__()' Side.__init__( self, corona ) - self._rails = [] + self.rails = [] for i in range(self.railsNb): - self._rails.append( HorizontalRail(self,i,self.getRailAxis(i)) ) + self.rails.append( HorizontalRail(self,i,self.getRailAxis(i)) ) #print ' Rail [%i] @%d' % (i,DbU.toLambda(self._rails[-1].axis)) return @@ -379,7 +388,7 @@ class NorthSide ( HorizontalSide ): 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 corner0 ( self, i ): return self.corners[chip.NorthWest][i] def corner1 ( self, i ): return self.corners[chip.NorthEast][i] @@ -388,20 +397,20 @@ class VerticalSide ( Side ): def __init__ ( self, corona ): Side.__init__( self, corona ) - self._rails = [] + self.rails = [] for i in range(self.railsNb): - self._rails.append( VerticalRail(self,i,self.getRailAxis(i)) ) + self.rails.append( VerticalRail(self,i,self.getRailAxis(i)) ) return def addBlockages ( self, sideXMin, sideXMax ): spans = IntervalSet() - for rail in self._rails: + for rail in self.rails: for via in rail.vias.values(): if via[1].getNet() != via[2].getNet(): continue spans.merge( via[1]._y - via[1]._height/2, via[1]._y + via[1]._height/2 ) - routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + routingGauge = self.corona.routingGauge for depth in range(self.getInnerRail(0).vias.values()[0][1].bottomDepth ,self.getInnerRail(0).vias.values()[0][1].topDepth ): blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer() @@ -410,8 +419,8 @@ class VerticalSide ( Side ): for chunk in spans.chunks: Horizontal.create( self.blockageNet , blockageLayer - , (chunk.getVMax()+chunk.getVMin())/2 - , chunk.getVMax() - chunk.getVMin() + pitch*2 + , (chunk.getVMax() + chunk.getVMin())/2 + , chunk.getVMax() - chunk.getVMin() + pitch*2 , sideXMin , sideXMax ) @@ -461,49 +470,44 @@ class EastSide ( VerticalSide ): class Corona ( object ): def __init__ ( self, block ): - #if not isinstance(block,plugins.chip.BlockPower.Block): - # raise ErrorMessage( 1, 'Attempt to create a Corona on a non-Block object.' ) + self.block = block + self.railsNb = Cfg.getParamInt('chip.block.rails.count' ).asInt() + self.hRailWidth = Cfg.getParamInt('chip.block.rails.hWidth' ).asInt() + self.vRailWidth = Cfg.getParamInt('chip.block.rails.vWidth' ).asInt() + self.hRailSpace = Cfg.getParamInt('chip.block.rails.hSpacing').asInt() + self.vRailSpace = Cfg.getParamInt('chip.block.rails.vSpacing').asInt() - self._railsNb = Cfg.getParamInt('chip.block.rails.count').asInt() - self._hRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.hWidth' ).asInt() ) - self._vRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.vWidth' ).asInt() ) - self._hRailSpace = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.hSpacing').asInt() ) - self._vRailSpace = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.vSpacing').asInt() ) - - self._block = block - self._innerBb = self._block.bb - self._block.path.getTransformation().applyOn( self._innerBb ) - self._innerBb.inflate( self._hRailSpace/2, self._vRailSpace/2 ) + self.innerBb = self.block.bb + self.block.path.getTransformation().applyOn( self.innerBb ) + self.innerBb.inflate( self.hRailSpace/2, self.vRailSpace/2 ) - if not self.useClockTree: self._railsNb -= 1 + if not self.block.conf.useClockTree: self.railsNb -= 1 - self._southSide = SouthSide( self ) - self._northSide = NorthSide( self ) - self._westSide = WestSide ( self ) - self._eastSide = EastSide ( self ) + self.southSide = SouthSide( self ) + self.northSide = NorthSide( self ) + self.westSide = WestSide ( self ) + self.eastSide = EastSide ( self ) return @property - def useClockTree ( self ): return self._block.useClockTree + def routingGauge ( self ): return self.block.conf.gaugeConf.routingGauge @property - def routingGauge ( self ): return self._block.routingGauge + def topLayerDepth ( self ): return self.block.conf.gaugeConf.topLayerDepth @property - def topLayerDepth ( self ): return self._block.topLayerDepth + def horizontalDepth ( self ): return self.block.conf.gaugeConf.horizontalDepth @property - def horizontalDepth ( self ): return self._block.horizontalDepth + def verticalDepth ( self ): return self.block.conf.gaugeConf.verticalDepth @property - def verticalDepth ( self ): return self._block.verticalDepth - @property - def blockageNet ( self ): return self._block.blockageNet + def blockageNet ( self ): return self.block.conf.blockageNet def getLayerDepth ( self, metal ): - return self.routingGauge.getLayerDepth( metal ) + return self.block.conf.gaugeConf.routingGauge.getLayerDepth( metal ) def getRailNet ( self, i ): - if self.useClockTree and i == self._railsNb-1: return self._block.cko - if i % 2: return self._block.vssi - return self._block.vddi + if self.block.conf.useClockTree and i == self.railsNb-1: return self.block.conf.coronaCk + if i % 2: return self.block.conf.coronaVss + return self.block.conf.coronaVdd def getHLayer ( self ): return self.routingGauge.getLayerGauge( self.horizontalDepth ).getLayer() @@ -512,76 +516,76 @@ class Corona ( object ): return self.routingGauge.getLayerGauge( self.verticalDepth ).getLayer() def connectBlock ( self ): - for plane in self._block.planes.values(): + 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 ] ) + 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 ) + 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 : [] - } + self.corners = { chip.SouthWest : [] + , chip.SouthEast : [] + , chip.NorthWest : [] + , chip.NorthEast : [] + } contactDepth = self.horizontalDepth if self.horizontalDepth > self.verticalDepth: contactDepth = self.verticalDepth UpdateSession.open() - 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 + 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.routingGauge.getContactLayer(contactDepth) - self._corners[chip.SouthWest].append( + self.corners[chip.SouthWest].append( Contact.create( net , self.routingGauge.getContactLayer(contactDepth) , xBL, yBL - , self._hRailWidth - , self._vRailWidth + , self.hRailWidth + , self.vRailWidth ) ) - self._corners[chip.NorthWest].append( + self.corners[chip.NorthWest].append( Contact.create( net , self.routingGauge.getContactLayer(contactDepth) , xBL, yTR - , self._hRailWidth - , self._vRailWidth + , self.hRailWidth + , self.vRailWidth ) ) - self._corners[chip.SouthEast].append( + self.corners[chip.SouthEast].append( Contact.create( net , self.routingGauge.getContactLayer(contactDepth) , xTR, yBL - , self._hRailWidth - , self._vRailWidth + , self.hRailWidth + , self.vRailWidth ) ) - self._corners[chip.NorthEast].append( + self.corners[chip.NorthEast].append( Contact.create( net , self.routingGauge.getContactLayer(contactDepth) , xTR, yTR - , self._hRailWidth - , self._vRailWidth + , self.hRailWidth + , self.vRailWidth ) ) - self._southSide.doLayout() - self._northSide.doLayout() - self._westSide .doLayout() - self._eastSide .doLayout() + self.southSide.doLayout() + self.northSide.doLayout() + self.westSide .doLayout() + self.eastSide .doLayout() - self._westSide.addBlockages() - self._eastSide.addBlockages() + self.westSide.addBlockages() + self.eastSide.addBlockages() UpdateSession.close() return diff --git a/cumulus/src/plugins/chip/BlockPower.py b/cumulus/src/plugins/chip/BlockPower.py index 78136e7b..2ba18c26 100644 --- a/cumulus/src/plugins/chip/BlockPower.py +++ b/cumulus/src/plugins/chip/BlockPower.py @@ -125,11 +125,11 @@ class Plane ( object ): 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) - ] + self.sides[ net ] = { chip.North : Side(self.block,chip.North,net,self.metal) + , chip.South : Side(self.block,chip.South,net,self.metal) + , chip.East : Side(self.block,chip.East ,net,self.metal) + , chip.West : Side(self.block,chip.West ,net,self.metal) + } sides = self.sides[ net ] if direction == Plane.Horizontal: @@ -147,7 +147,7 @@ class Plane ( object ): def doLayout ( self ): for sidesOfNet in self.sides.values(): - for side in sidesOfNet: + for side in sidesOfNet.values(): side.doLayout() return @@ -166,8 +166,8 @@ class GoCb ( object ): 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 go.getNet().getType() == Net.Type.POWER: rootNet = self.block.conf.coronaVdd + if go.getNet().getType() == Net.Type.GROUND: rootNet = self.block.conf.coronaVss if not rootNet: return if self.block.activePlane: @@ -179,37 +179,35 @@ class GoCb ( object ): return -class Block ( chip.Configuration.ChipConfWrapper ): +class Block ( object ): def __init__ ( self, conf ): - chip.Configuration.ChipConfWrapper.__init__( self, conf.gaugeConf, conf.chipConf ) - self.path = Path( self.cores[0] ) + self.conf = conf + self.path = Path( self.conf.icore ) self.block = self.path.getTailInstance().getMasterCell() self.bb = self.block.getAbutmentBox() self.planes = { } self.activePlane = None - routingGauge = CRL.AllianceFramework.get().getRoutingGauge() - for layerGauge in routingGauge.getLayerGauges(): + for layerGauge in self.conf.gaugeConf.routingGauge.getLayerGauges(): self.planes[ layerGauge.getLayer().getName() ] = Plane( self, layerGauge.getLayer() ) return def connectPower ( 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.' ) + if not self.conf.coronaVdd or not self.conf.coronaVss: + print ErrorMessage( 1, 'Cannot build block power terminals as core vdd and/or vss are not known.' ) return goCb = GoCb( self ) query = Query() query.setGoCallback( goCb ) query.setCell( self.block ) - query.setArea( self.bb ) + query.setArea( self.block.getAbutmentBox() ) query.setFilter( Query.DoComponents|Query.DoTerminalCells ) - routingGauge = CRL.AllianceFramework.get().getRoutingGauge() - for layerGauge in routingGauge.getLayerGauges(): + for layerGauge in self.conf.gaugeConf.routingGauge.getLayerGauges(): self.activePlane = self.planes[ layerGauge.getLayer().getName() ] query.setBasicLayer( layerGauge.getLayer().getBasicLayer() ) query.doQuery() @@ -218,24 +216,24 @@ class Block ( chip.Configuration.ChipConfWrapper ): def connectClock ( self ): - if not self.useClockTree: + if not self.conf.useClockTree: print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." ) return - - if not self.cko: + + if not self.conf.coronaCk: print ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' ) return - + blockCk = None for plug in self.path.getTailInstance().getPlugs(): - if plug.getNet() == self.cko: + if plug.getNet() == self.conf.coronaCk: blockCk = plug.getMasterNet() - + if not blockCk: print ErrorMessage( 1, 'Block <%s> has no net connected to the clock <%s>.' % (self.path.getTailInstance().getName(),self.ck.getName()) ) return - + htPlugs = [] ffPlugs = [] for plug in blockCk.getPlugs(): @@ -244,13 +242,13 @@ class Block ( chip.Configuration.ChipConfWrapper ): else: if plug.getInstance().getMasterCell().isTerminal(): ffPlugs.append( plug ) - + if len(ffPlugs) > 0: message = 'Clock <%s> of block <%s> is not organized as a H-Tree.' \ % (blockCk.getName(),self.path.getTailInstance().getName()) print ErrorMessage( 1, message ) return - + if len(htPlugs) > 1: message = 'Block <%s> has not exactly one H-Tree connecteds to the clock <%s>:' \ % (self.path.getTailInstance().getName(),blockCk.getName()) @@ -258,29 +256,29 @@ class Block ( chip.Configuration.ChipConfWrapper ): message += '\n - %s' % plug print ErrorMessage( 1, message ) return - + UpdateSession.open() - bufferRp = self.rpAccessByOccurrence( Occurrence(htPlugs[0], self.path), self.cko ) + bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], self.path), self.conf.coronaCk ) blockAb = self.block.getAbutmentBox() self.path.getTransformation().applyOn( blockAb ) - layerGauge = self.routingGauge.getLayerGauge(self.verticalDepth) + layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth) - contact = Contact.create( self.cko - , self.routingGauge.getRoutingLayer(self.verticalDepth) + contact = Contact.create( self.conf.coronaCk + , self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth) , bufferRp.getX() , blockAb.getYMax() , layerGauge.getViaWidth() , layerGauge.getViaWidth() ) - segment = self.createVertical( bufferRp, contact, bufferRp.getX() ) - + segment = self.conf.createVertical( bufferRp, contact, bufferRp.getX() ) + self.activePlane = self.planes[ layerGauge.getLayer().getName() ] bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() ) self.path.getTransformation().getInvert().applyOn( bb ) - self.activePlane.addTerminal( self.cko, Plane.Vertical, bb ) + self.activePlane.addTerminal( self.conf.coronaCk, Plane.Vertical, bb ) UpdateSession.close() - + return def doLayout ( self ): diff --git a/cumulus/src/plugins/chip/Chip.py b/cumulus/src/plugins/chip/Chip.py new file mode 100644 index 00000000..a395258a --- /dev/null +++ b/cumulus/src/plugins/chip/Chip.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# +# This file is part of the Coriolis Software. +# Copyright (c) UPMC 2014-2018, 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/Chip.py" | +# +-----------------------------------------------------------------+ + + +try: + import sys + import traceback + import os.path + import optparse + import math + import cProfile + import pstats + 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 + import helpers + from helpers import ErrorMessage + from helpers import WarningMessage + import Etesian + import Anabatic + import Katana + import Unicorn + import plugins + import clocktree.ClockTree + import chip.Configuration + import chip.BlockPower + import chip.BlockCorona + import chip.PadsCorona +except ImportError, e: + serror = str(e) + if serror.startswith('No module named'): + module = serror.split()[-1] + print '[ERROR] The <%s> python module or symbol cannot be loaded.' % module + print ' Please check the integrity of the package.' + if str(e).find('cannot open shared object file'): + library = serror.split(':')[0] + print '[ERROR] The <%s> shared library cannot be loaded.' % library + print ' Under RHEL 6, you must be under devtoolset-2.' + print ' (scl enable devtoolset-2 bash)' + 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) + + +# -------------------------------------------------------------------- +# PlaceRoute class + + +class PlaceRoute ( object ): + + def __init__ ( self, conf ): + self.conf = conf + self.validated = False + return + + + def _refresh ( self ): + if self.conf.viewer: self.conf.viewer.fit() + return + + + def validate ( self ): + self.validated = True + if len(self.conf.cores) < 1: self.validated = False + + coreAb = self.conf.core.getAbutmentBox() + if (not coreAb.isEmpty()): + if coreAb.getWidth () <= self.conf.coreSize.getWidth() \ + and coreAb.getHeight() <= self.conf.coreSize.getHeight(): + self.conf.coreSize = coreAb + else: + print ErrorMessage( 1, [ 'Core %s already have an abutment box, bigger than the requested one:' + % self.conf.cores[0].getName() + , " Cell abutment box: %s" % str(coreAb) + , " Maximum abutment box: %s" % str(self.conf.coreSize) ] ) + self.validated = False + + return self.validated + + + def doCoronaFloorplan ( self ): + if not self.validated: return + + UpdateSession.open() + self.conf.core.setAbutmentBox( self.conf.coreSize ) + coronaAb = self.conf.corona.getAbutmentBox() + x = (coronaAb.getWidth () - self.conf.coreSize.getWidth ()) / 2 + y = (coronaAb.getHeight() - self.conf.coreSize.getHeight()) / 2 + x = x - (x % self.conf.getSliceHeight()) + y = y - (y % self.conf.getSliceHeight()) + self.conf.icore.setTransformation ( Transformation(x,y,Transformation.Orientation.ID) ) + self.conf.icore.setPlacementStatus( Instance.PlacementStatus.FIXED ) + UpdateSession.close() + return + + + def doCorePlacement ( self ): + if not self.validated: return + + coreCell = self.conf.core + + checkUnplaced = plugins.CheckUnplaced( coreCell, plugins.NoFlags ) + if not checkUnplaced.check(): return + + coreCk = None + for plug in self.conf.coronaCk.getPlugs(): + if plug.getInstance() == self.conf.icore: + coreCk = plug.getMasterNet() + if not coreCk: + print WarningMessage( 'Core <%s> is not connected to chip clock.' % self.conf.icore.getName() ) + + if self.conf.useClockTree and coreCk: + ht = clocktree.ClockTree.HTree.create( self.conf, coreCell, coreCk, coreCell.getAbutmentBox() ) + ht.addCloned( self.conf.cell ) + etesian = Etesian.EtesianEngine.create( coreCell ) + etesian.setViewer( self.conf.viewer ) + etesian.place() + etesian.destroy() + + ht.connectLeaf() + ht.route() + ht.save( self.conf.cell ) + else: + etesian = Etesian.EtesianEngine.create( coreCell ) + etesian.place() + etesian.destroy() + return + + + def doChipPlacement ( self ): + padsCorona = chip.PadsCorona.Corona( self.conf ) + self.validated = padsCorona.validate() + if not self.validated: return False + + padsCorona.doLayout() + self.validate() + self.doCoronaFloorplan() + self._refresh() + + self.doCorePlacement() + self._refresh() + + coreBlock = chip.BlockPower.Block( self.conf ) + coreBlock.connectPower() + coreBlock.connectClock() + coreBlock.doLayout() + self._refresh() + + coreCorona = chip.BlockCorona.Corona( coreBlock ) + coreCorona.connectPads ( padsCorona ) + coreCorona.connectBlock() + coreCorona.doLayout() + self._refresh() + + return + + + def doChipRouting ( self ): + katana = Katana.KatanaEngine.create( self.conf.corona ) + katana.printConfiguration () + katana.digitalInit () + #katana.runNegociatePreRouted() + katana.runGlobalRouter () + katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet ) + katana.layerAssign ( Anabatic.EngineNoNetLayerAssign ) + katana.runNegociate ( Katana.Flags.NoFlags ) + success = katana.getToolSuccess() + katana.finalizeLayout() + katana.destroy() + + return diff --git a/cumulus/src/plugins/chip/Configuration.py b/cumulus/src/plugins/chip/Configuration.py index 69638c81..45d30092 100644 --- a/cumulus/src/plugins/chip/Configuration.py +++ b/cumulus/src/plugins/chip/Configuration.py @@ -26,9 +26,10 @@ from Hurricane import Path from Hurricane import Occurrence from Hurricane import Net from Hurricane import RoutingPad -from Hurricane import Contact from Hurricane import Horizontal from Hurricane import Vertical +from Hurricane import Contact +from Hurricane import Pin from Hurricane import Plug from Hurricane import Instance import CRL @@ -37,6 +38,7 @@ from helpers import trace from helpers import ErrorMessage from helpers import WarningMessage from plugins import getParameter +import chip def breakpoint ( editor, level, message ): @@ -120,84 +122,115 @@ class GaugeConf ( object ): ExpandWidth = 0x0040 def __init__ ( self ): - self._cellGauge = None - self._routingGauge = None - self._topLayerDepth = 0 + self.cellGauge = None + self.ioPadGauge = None + self.routingGauge = None + self.topLayerDepth = 0 self._plugToRp = { } self._rpToAccess = { } self._loadRoutingGauge() return - def getSliceHeight ( self ): return self._cellGauge.getSliceHeight() - def getSliceStep ( self ): return self._cellGauge.getSliceStep() + def getSliceHeight ( self ): return self.cellGauge.getSliceHeight() + def getSliceStep ( self ): return self.cellGauge.getSliceStep() + def getIoPadHeight ( self ): return self.ioPadGauge.getSliceHeight() + def getIoPadStep ( self ): return self.ioPadGauge.getSliceStep() + def getIoPadPitch ( self ): return self.ioPadGauge.getPitch() + def getIoPadGauge ( self ): return self.ioPadGauge + def getHRoutingGauge ( self ): return self.routingGauge.getLayerGauge( self.horizontalDepth ) + def getVRoutingGauge ( self ): return self.routingGauge.getLayerGauge( self.verticalDepth ) def _loadRoutingGauge ( self ): - self._cellGauge = CRL.AllianceFramework.get().getCellGauge() - self._routingGauge = CRL.AllianceFramework.get().getRoutingGauge() + gaugeName = Cfg.getParamString('anabatic.routingGauge').asString() + self.cellGauge = CRL.AllianceFramework.get().getCellGauge( gaugeName ) + self.routingGauge = CRL.AllianceFramework.get().getRoutingGauge( gaugeName ) topLayer = Cfg.getParamString('katabatic.topRoutingLayer').asString() - self._topLayerDepth = 0 - for layerGauge in self._routingGauge.getLayerGauges(): + self.topLayerDepth = 0 + for layerGauge in self.routingGauge.getLayerGauges(): if layerGauge.getLayer().getName() == topLayer: - self._topLayerDepth = layerGauge.getDepth() + self.topLayerDepth = layerGauge.getDepth() break - if not self._topLayerDepth: + if not self.topLayerDepth: print WarningMessage( 'Gauge top layer not defined, using top of gauge (%d).' \ - % self._routingGauge.getDepth() ) - self._topLayerDepth = self._routingGauge.getDepth() + % self.routingGauge.getDepth() ) + self.topLayerDepth = self.routingGauge.getDepth() - self._horizontalDepth = -1 - self._verticalDepth = -1 - self._horizontalDeepDepth = -1 - self._verticalDeepDepth = -1 - for depth in range(0,self._topLayerDepth+1): - if self._routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.PinOnly: + self.horizontalDepth = -1 + self.verticalDepth = -1 + self.horizontalDeepDepth = -1 + self.verticalDeepDepth = -1 + for depth in range(0,self.topLayerDepth+1): + if self.routingGauge.getLayerGauge(depth).getType() == RoutingLayerGauge.PinOnly: continue - if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: - if self._horizontalDeepDepth < 0: - self._horizontalDeepDepth = depth - self._horizontalDepth = depth - if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: - if self._verticalDeepDepth < 0: - self._verticalDeepDepth = depth - self._verticalDepth = depth + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: + if self.horizontalDeepDepth < 0: + self.horizontalDeepDepth = depth + self.horizontalDepth = depth + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: + if self.verticalDeepDepth < 0: + self.verticalDeepDepth = depth + self.verticalDepth = depth return - def _createContact ( self, net, x, y, flags ): - if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth - else: depth = self._horizontalDepth + def _loadIoPadGauge ( self, ioPadGaugeName ): + self.ioPadGauge = CRL.AllianceFramework.get().getCellGauge( ioPadGaugeName ) + if not self.ioPadGauge: + print WarningMessage( 'IO pad gauge "%s" not found.' % ioPadGaugeName ) + return + def isHorizontal ( self, layer ): + mask = layer.getMask() + for lg in self.routingGauge.getLayerGauges(): + if lg.getLayer().getMask() == mask: + if lg.getDirection() == RoutingLayerGauge.Horizontal: return True + return False + + print ErrorMessage( 1, 'GaugeConf.isHorizontal(): Layer "%s" is not part of gauge "%s", cannot know preferred direction.' \ + % (layer.getName(), self.routingGauge.getName()) ) + return False + + def isVertical ( self, layer ): return not self.isHorizontal( layer ) + + def _createContact ( self, net, x, y, flags ): + if flags & GaugeConf.DeepDepth: depth = self.horizontalDeepDepth + else: depth = self.horizontalDepth + + if self.horizontalDepth > self.verticalDepth: depth -= 1 + + trace( 550, '\t%s, horizontalDepth:%d, gaugeDepth:%d\n' + % (self.routingGauge,self.horizontalDepth,self.routingGauge.getDepth())) return Contact.create( net - , self._routingGauge.getContactLayer(depth) + , self.routingGauge.getContactLayer(depth) , x, y - , self._routingGauge.getLayerGauge(depth).getViaWidth() - , self._routingGauge.getLayerGauge(depth).getViaWidth() + , self.routingGauge.getLayerGauge(depth).getViaWidth() + , self.routingGauge.getLayerGauge(depth).getViaWidth() ) def _getNearestHorizontalTrack ( self, bb, y, flags ): - if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth - else: depth = self._horizontalDepth + if flags & GaugeConf.DeepDepth: depth = self.horizontalDeepDepth + else: depth = self.horizontalDepth - index = self._routingGauge.getLayerGauge(depth).getTrackIndex( bb.getYMin(), bb.getYMax(), y, RoutingLayerGauge.Nearest ) - return self._routingGauge.getLayerGauge(depth).getTrackPosition( bb.getYMin(), index ) + index = self.routingGauge.getLayerGauge(depth).getTrackIndex( bb.getYMin(), bb.getYMax(), y, RoutingLayerGauge.Nearest ) + return self.routingGauge.getLayerGauge(depth).getTrackPosition( bb.getYMin(), index ) def _getNearestVerticalTrack ( self, bb, x, flags ): - if flags & GaugeConf.DeepDepth: depth = self._verticalDeepDepth - else: depth = self._verticalDepth + if flags & GaugeConf.DeepDepth: depth = self.verticalDeepDepth + else: depth = self.verticalDepth - index = self._routingGauge.getLayerGauge(depth).getTrackIndex( bb.getXMin(), bb.getXMax(), x, RoutingLayerGauge.Nearest ) - return self._routingGauge.getLayerGauge(depth).getTrackPosition( bb.getXMin(), index ) + index = self.routingGauge.getLayerGauge(depth).getTrackIndex( bb.getXMin(), bb.getXMax(), x, RoutingLayerGauge.Nearest ) + return self.routingGauge.getLayerGauge(depth).getTrackPosition( bb.getXMin(), index ) def _createHorizontal ( self, source, target, y, flags ): - if flags & GaugeConf.DeepDepth: depth = self._horizontalDeepDepth - else: depth = self._horizontalDepth + if flags & GaugeConf.DeepDepth: depth = self.horizontalDeepDepth + else: depth = self.horizontalDepth - layer = self._routingGauge.getRoutingLayer(depth) + layer = self.routingGauge.getRoutingLayer(depth) if flags & GaugeConf.UseContactWidth: width = source.getBoundingBox(layer.getBasicLayer()).getHeight() - else: width = self._routingGauge.getLayerGauge(depth).getWireWidth() + else: width = self.routingGauge.getLayerGauge(depth).getWireWidth() if flags & GaugeConf.ExpandWidth: width += DbU.fromLambda( 1.0 ) segment = Horizontal.create( source, target, layer, y, width ) @@ -205,13 +238,13 @@ class GaugeConf ( object ): return segment def _createVertical ( self, source, target, x, flags ): - if flags & GaugeConf.DeepDepth: depth = self._verticalDeepDepth - else: depth = self._verticalDepth + if flags & GaugeConf.DeepDepth: depth = self.verticalDeepDepth + else: depth = self.verticalDepth - layer = self._routingGauge.getRoutingLayer(depth) + layer = self.routingGauge.getRoutingLayer(depth) if flags & GaugeConf.UseContactWidth: width = source.getBoundingBox(layer.getBasicLayer()).getWidth() - else: width = self._routingGauge.getLayerGauge(depth).getWireWidth() + else: width = self.routingGauge.getLayerGauge(depth).getWireWidth() if flags & GaugeConf.ExpandWidth: width += DbU.fromLambda( 1.0 ) segment = Vertical.create( source, target, layer, x, width ) @@ -226,17 +259,17 @@ class GaugeConf ( object ): return self._rpToAccess[rp] if flags & GaugeConf.DeepDepth: - hdepth = self._horizontalDeepDepth - vdepth = self._verticalDeepDepth + hdepth = self.horizontalDeepDepth + vdepth = self.verticalDeepDepth else: - hdepth = self._horizontalDepth - vdepth = self._verticalDepth + hdepth = self.horizontalDepth + vdepth = self.verticalDepth - hpitch = self._routingGauge.getLayerGauge(hdepth).getPitch() - hoffset = self._routingGauge.getLayerGauge(hdepth).getOffset() - contact1 = Contact.create( rp, self._routingGauge.getContactLayer(0), 0, 0 ) - midSliceY = contact1.getY() - (contact1.getY() % self._cellGauge.getSliceHeight()) \ - + self._cellGauge.getSliceHeight() / 2 + hpitch = self.routingGauge.getLayerGauge(hdepth).getPitch() + hoffset = self.routingGauge.getLayerGauge(hdepth).getOffset() + contact1 = Contact.create( rp, self.routingGauge.getContactLayer(0), 0, 0 ) + midSliceY = contact1.getY() - (contact1.getY() % self.cellGauge.getSliceHeight()) \ + + self.cellGauge.getSliceHeight() / 2 midTrackY = midSliceY - ((midSliceY - hoffset) % hpitch) dy = midSliceY - contact1.getY() @@ -252,29 +285,29 @@ class GaugeConf ( object ): for depth in range(1,stopDepth): xoffset = 0 if flags & GaugeConf.OffsetRight1 and depth == 1: - xoffset = self._routingGauge.getLayerGauge(depth+1).getPitch() + xoffset = self.routingGauge.getLayerGauge(depth+1).getPitch() contact2 = Contact.create( rp.getNet() - , self._routingGauge.getContactLayer(depth) + , self.routingGauge.getContactLayer(depth) , contact1.getX() + xoffset , contact1.getY() - , self._routingGauge.getLayerGauge(depth).getViaWidth() - , self._routingGauge.getLayerGauge(depth).getViaWidth() + , self.routingGauge.getLayerGauge(depth).getViaWidth() + , self.routingGauge.getLayerGauge(depth).getViaWidth() ) trace( 550, contact2 ) - if self._routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: + if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: segment = Horizontal.create( contact1 , contact2 - , self._routingGauge.getRoutingLayer(depth) + , self.routingGauge.getRoutingLayer(depth) , contact1.getY() - , self._routingGauge.getLayerGauge(depth).getWireWidth() + , self.routingGauge.getLayerGauge(depth).getWireWidth() ) trace( 550, segment ) else: segment = Vertical.create( contact1 , contact2 - , self._routingGauge.getRoutingLayer(depth) + , self.routingGauge.getRoutingLayer(depth) , contact1.getX() - , self._routingGauge.getLayerGauge(depth).getWireWidth() + , self.routingGauge.getLayerGauge(depth).getWireWidth() ) trace( 550, segment ) contact1 = contact2 @@ -343,75 +376,37 @@ class GaugeConf ( object ): return -# ------------------------------------------------------------------- -# Class : "Configuration.GaugeConfWrapper". - -class GaugeConfWrapper ( object ): - - def __init__ ( self, conf ): - #print id(conf), type(conf) - #if not isinstance(conf,GaugeConf): - # raise ErrorMessage( 1, 'Attempt to create a GaugeConfWrapper() from non-GaugeConf object.' ) - self._gaugeConf = conf - return - - @property - def gaugeConf ( self ): return self._gaugeConf - - @property - def routingGauge ( self ): return self._gaugeConf._routingGauge - @property - def topLayerDepth ( self ): return self._gaugeConf._topLayerDepth - @property - def horizontalDepth ( self ): return self._gaugeConf._horizontalDepth - @property - def verticalDepth ( self ): return self._gaugeConf._verticalDepth - @property - def horizontalDeepDepth ( self ): return self._gaugeConf._horizontalDeepDepth - @property - def verticalDeepDepth ( self ): return self._gaugeConf._verticalDeepDepth - - def loadRoutingGauge ( self ): self._gaugeConf._loadRoutingGauge() - - def rpByOccurrence ( self, occurrence, net ): - return self._gaugeConf._rpByOccurrence ( occurrence, net ) - - def rpByPlugName ( self, instance, plugName, net ): - return self._gaugeConf._rpByPlugName ( instance, plugName, net ) - - def rpAccess ( self, rp, flags=0 ): - return self._gaugeConf._rpAccess( rp, flags ) - - def rpAccessByOccurrence ( self, occurrence, net, flags=0 ): - return self.gaugeConf._rpAccessByOccurrence ( occurrence, net, flags ) - - def rpAccessByPlugName ( self, instance, plugName, net, flags=0 ): - return self._gaugeConf._rpAccessByPlugName( instance, plugName, net, flags ) - - def createContact ( self, net, x, y, flags=0 ): - return self._gaugeConf._createContact( net, x, y, flags ) - - def createHorizontal ( self, source, target, y, flags=0 ): - return self._gaugeConf._createHorizontal( source, target, y, flags ) - - def createVertical ( self, source, target, x, flags=0 ): - return self._gaugeConf._createVertical( source, target, x, flags ) - - def getNearestHorizontalTrack ( self, bb, y, flags ): - return self._gaugeConf._getNearestHorizontalTrack ( bb, y, flags ) - - def getNearestVerticalTrack ( self, bb, x, flags ): - return self._gaugeConf._getNearestVerticalTrack( bb, x, flags ) - - def setStackPosition ( self, topContact, x, y ): - self._gaugeConf._setStackPosition( topContact, x, y ) - - # ------------------------------------------------------------------- # Class : "Configuration.ChipConf". class ChipConf ( object ): + @staticmethod + def _toSymbolic ( u, rounding ): + oneLambda = DbU.fromLambda( 1.0 ) + remainder = u % oneLambda + if remainder: + if rounding == chip.Superior: u = u + (oneLambda - remainder) + else: u = u - remainder + return u + + + @staticmethod + def toSymbolic ( v, rounding ): + if isinstance(v,long): return ChipConf._toSymbolic( v, rounding ) + if isinstance(v,Box): + if rounding & chip.Inwards: + roundings = [ chip.Superior, chip.Superior, chip.Inferior, chip.Inferior ] + else: + roundings = [ chip.Inferior, chip.Inferior, chip.Superior, chip.Superior ] + xMin = ChipConf._toSymbolic( v.getXMin(), roundings[0] ) + yMin = ChipConf._toSymbolic( v.getYMin(), roundings[1] ) + xMax = ChipConf._toSymbolic( v.getXMax(), roundings[2] ) + yMax = ChipConf._toSymbolic( v.getYMax(), roundings[3] ) + return Box( xMin, yMin, xMax, yMax ) + return v + + @staticmethod def _readChipSize( chipConfigDict ): if not chipConfigDict.has_key('chip.size'): return Box() @@ -422,7 +417,7 @@ class ChipConf ( object ): 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]) ) + return Box( 0, 0, chipSize[0], chipSize[1] ) @staticmethod @@ -437,7 +432,7 @@ class ChipConf ( object ): 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]) ) + return Box( 0, 0, coreSize[0], coreSize[1] ) @staticmethod @@ -449,357 +444,656 @@ class ChipConf ( object ): return useClockTree + def _loadIoPadGauge ( self, chipConfigDict ): + if not chipConfigDict.has_key('pads.ioPadGauge'): + print ErrorMessage( 1, 'The IO pad gauge configuration paramater "pads.ioPadGauge" is missing.' ) + return + self.gaugeConf._loadIoPadGauge( chipConfigDict['pads.ioPadGauge'] ) + return + + def _readPads ( self, chipConfigDict, keyword ): if not chipConfigDict.has_key(keyword): return [] - padNameList = chipConfigDict[keyword] - if not isinstance(padNameList,list): + padConfList = chipConfigDict[keyword] + if not isinstance(padConfList,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).' + for i in range(len(padConfList)): + position = None + instanceName = None + if isinstance(padConfList[i],str): + instanceName = padConfList[i] + elif isinstance(padConfList[i],list): + self.padsHavePosition = True + if isinstance(padConfList[i][0],long) and isinstance(padConfList[i][1],str): + position = padConfList[i][0] + instanceName = padConfList[i][1] + + if not instanceName: + print ErrorMessage( 1, 'The element [%d] of list %s is neither a string nor a list "[pos,name]" (skipped).' % (i,keyword) ) continue - instance = self._cell.getInstance( padNameList[i] ) + instance = self.cell.getInstance( instanceName ) if not instance: print ErrorMessage( 1, 'The pad [%d] (%s) of list %s do not exists in netlist (skipped).' - % (i,padNameList[i],keyword) ) + % (i,instanceName,keyword) ) continue - if (not af.isPad(instance.getMasterCell().getName())): + if (instance.getMasterCell().getAbutmentBox().getHeight() != self.gaugeConf.getIoPadHeight()): print ErrorMessage( 1, 'The pad [%d] (%s) of list %s is not an instance of a pad cell (skipped).' - % (i,padNameList[i],keyword) ) + % (i,instanceName,keyword) ) continue - padList.append( instance ) - - if not self._clockPad and instance.getMasterCell().getName() == self._pckName: - self._clockPad = instance - - if not self._powerPad and instance.getMasterCell().getName() == self._pvddickName: - self._powerPad = instance + padList.append( [ position, 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 - if name == self._blockageName: self._blockageNet = net - return - - def __init__ ( self, chipConfigDict, cell, viewer=None ): + trace( 550, '\tONE LAMBDA = %s\n' % DbU.getValueString(DbU.fromLambda(1.0)) ) + if not isinstance(chipConfigDict,dict): - raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' ) + raise ErrorMessage( 1, 'The "chip" variable is not a dictionnary.' ) + + self.chipMode = True + if len(chipConfigDict.keys()) == 0: self.chipMode = False - self._validated = True - self._cell = cell - self._viewer = viewer + self.validated = True + self.gaugeConf = GaugeConf() + self.cell = cell + self.viewer = viewer # Block Corona parameters. - self._railsNb = 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 Pad names. - self._pckName = getParameter('chip', 'chip.pad.pck' ).asString() - self._pvddickName = getParameter('chip', 'chip.pad.pvddick').asString() - self._pvssickName = getParameter('chip', 'chip.pad.pvssick').asString() - self._pvddeckName = getParameter('chip', 'chip.pad.pvddeck').asString() - self._pvsseckName = getParameter('chip', 'chip.pad.pvsseck').asString() - # Global Net names. - self._vddeName = "vdde" - self._vddiName = "vddi" - self._vsseName = "vsse" - self._vssiName = "vssi" - self._ckiName = "ck" - self._ckoName = "cko" - self._ckName = "pad" - self._blockageName = "blockagenet" - # Global Nets. - self._vdde = None - self._vddi = None - self._vsse = None - self._vssi = None - self._cki = None - self._cko = None - self._ck = None - self._blockageNet = None + self.railsNb = getParameter('chip','chip.block.rails.count' ).asInt() + self.hRailWidth = getParameter('chip','chip.block.rails.hWidth' ).asInt() + self.vRailWidth = getParameter('chip','chip.block.rails.vWidth' ).asInt() + self.hRailSpace = getParameter('chip','chip.block.rails.hSpacing').asInt() + self.vRailSpace = getParameter('chip','chip.block.rails.vSpacing').asInt() + # Global Net names. + self.blockageName = "blockagenet" + # Global Nets. + self.coronaVdd = None + self.coronaVss = None + self.coronaCk = None + self.blockageNet = None - self._clockPad = None - self._powerPad = None - self._cores = [] - self._southPads = self._readPads( chipConfigDict, 'pads.south' ) - self._northPads = self._readPads( chipConfigDict, 'pads.north' ) - self._eastPads = self._readPads( chipConfigDict, 'pads.east' ) - self._westPads = self._readPads( chipConfigDict, 'pads.west' ) - self._coreSize = ChipConf._readCoreSize( chipConfigDict ) - self._chipSize = ChipConf._readChipSize( chipConfigDict ) - self._padWidth = 0 - self._padHeight = 0 - self._useClockTree = ChipConf._readClockTree( chipConfigDict ) + if self.chipMode: + self._loadIoPadGauge( chipConfigDict ) - minHCorona = self._railsNb*(self._hRailWidth + self._hRailSpace) + self._hRailSpace - minVCorona = self._railsNb*(self._vRailWidth + self._vRailSpace) + self._vRailSpace - if minHCorona > minVCorona: self._minCorona = minHCorona*2 - else: self._minCorona = minVCorona*2 + self.coronas = [] + self.cores = [] + if self.chipMode: + self.padsHavePosition = False + self.southPads = self._readPads( chipConfigDict, 'pads.south' ) + self.northPads = self._readPads( chipConfigDict, 'pads.north' ) + self.eastPads = self._readPads( chipConfigDict, 'pads.east' ) + self.westPads = self._readPads( chipConfigDict, 'pads.west' ) + self.coreSize = ChipConf._readCoreSize( chipConfigDict ) + self.chipSize = ChipConf._readChipSize( chipConfigDict ) + self.useClockTree = ChipConf._readClockTree( chipConfigDict ) - self.checkPads() - self.computeChipSize() - self.checkChipSize() - self.findPowerAndClockNets() + minHCorona = self.railsNb*(self.hRailWidth + self.hRailSpace) + self.hRailSpace + minVCorona = self.railsNb*(self.vRailWidth + self.vRailSpace) + self.vRailSpace + if minHCorona > minVCorona: self.minCorona = minHCorona*2 + else: self.minCorona = minVCorona*2 + + self.checkPads() + self.checkCorona() + self.computeChipSize() + #self.checkChipSize() + self.findPowerAndClockNets() return + @property + def icorona ( self ): return self.coronas[0] + + @property + def corona ( self ): return self.coronas[0].getMasterCell() + + @property + def icore ( self ): return self.cores[0] + + @property + def core ( self ): return self.cores[0].getMasterCell() + + + def getInstanceAb ( self, instance ): + ab = instance.getMasterCell().getAbutmentBox() + instance.getTransformation().applyOn( ab ) + + if instance.getCell() == self.cell: return ab + + if instance.getCell() != self.corona: + print ErrorMessage( 1, 'ChipConf.getInstanceAb(): Instance "%s" neither belong to chip or corona.' % instance.getName() ) + return ab + + self.icorona.getTransformation().applyOn( ab ) + return ab + + + def getCoronaNet ( self, chipNet ): + for plug in chipNet.getPlugs(): + if plug.getInstance() == self.icorona: + return plug.getMasterNet() + return None + + + def toRoutingGauge ( self, uMin, uMax, layer ): + trace( 550, ',+', '\ttoRoutingGauge() [%s %s] %s\n' \ + % (DbU.getValueString(uMin), DbU.getValueString(uMax), layer) ) + + ab = self.corona.getAbutmentBox() + lg = None + mask = layer.getMask() + for layerGauge in self.gaugeConf.routingGauge.getLayerGauges(): + if layerGauge.getLayer().getMask() == mask: + lg = layerGauge + trace( 550, '\tUsing layer gauge %s\n' % str(lg) ) + break + + if uMax < uMin: uMin, uMax = uMax, uMin + if lg: + if lg.getDirection() == RoutingLayerGauge.Horizontal: + abMin = ab.getYMin() + abMax = ab.getYMax() + else: + abMin = ab.getXMin() + abMax = ab.getXMax() + + iTrackMin = lg.getTrackIndex( abMin, abMax, uMin, RoutingLayerGauge.Superior ) + iTrackMax = lg.getTrackIndex( abMin, abMax, uMax, RoutingLayerGauge.Inferior ) + if iTrackMax < iTrackMin: iTrackMax = iTrackMin + + uTrackMin = lg.getTrackPosition( abMin, iTrackMin ) + uTrackMax = lg.getTrackPosition( abMin, iTrackMax ) + + axis = (uTrackMax + uTrackMin) / 2 + width = (iTrackMax - iTrackMin) * lg.getPitch() + lg.getWireWidth() + + if self.gaugeConf.routingGauge.isSymbolic(): + oneLambda = DbU.fromLambda( 1.0 ) + if axis % oneLambda: + axis -= oneLambda / 2 + width -= oneLambda + + trace( 550, '\t[%i %i]\n' % (iTrackMin, iTrackMax) ) + trace( 550, '\taxis: %sl %s\n' % (DbU.toLambda(axis ), DbU.getValueString(axis )) ) + trace( 550, '\twidth: %sl %s\n' % (DbU.toLambda(width), DbU.getValueString(width)) ) + else: + axis = (uMax + uMin) / 2 + width = (uMax - uMin) + + trace( 550, '-' ) + return axis, width + + + def coronaHorizontal ( self, chipNet, layer, chipY, width, chipXMin, chipXMax ): + trace( 550, ',+', '\tChipConf.coronaHorizontal\n' ) + + coronaAb = self.getInstanceAb( self.icorona ) + coronaNet = self.getCoronaNet ( chipNet ) + if not coronaNet: return None + + coronaY = chipY - coronaAb.getYMin() + dxMin = ChipConf.toSymbolic( chipXMin - coronaAb.getXMin(), chip.Superior ) + dxMax = ChipConf.toSymbolic( chipXMax - coronaAb.getXMin(), chip.Inferior ) + + trace( 550, '\t| chipNet: %s %s\n' % (chipNet, layer) ) + trace( 550, '\t| Real\n' ) + trace( 550, '\t| axis: %10s\n' % DbU.getValueString(coronaY) ) + trace( 550, '\t| width:%10s\n' % DbU.getValueString(width) ) + trace( 550, '\t| dxMin:%10s (%sl)\n' \ + % (DbU.getValueString(chipXMin - coronaAb.getXMin()), DbU.toLambda(chipXMin - coronaAb.getXMin()) ) ) + trace( 550, '\t| dxMax:%10s\n' % DbU.getValueString(chipXMax - coronaAb.getXMin()) ) + + coronaY, width = self.toRoutingGauge( coronaY - width/2, coronaY + width/2, layer ) + + trace( 550, '\t| On Grid\n' ) + trace( 550, '\t| axis: %10sl or %10s\n' % (DbU.toLambda(coronaY), DbU.getValueString(coronaY)) ) + trace( 550, '\t| width:%10sl or %10s\n' % (DbU.toLambda(width) , DbU.getValueString(width)) ) + trace( 550, '\t| dxMin:%10sl\n' % DbU.toLambda(dxMin) ) + trace( 550, '\t| dxMax:%10sl\n' % DbU.toLambda(dxMax) ) + + h = Horizontal.create( coronaNet, layer, coronaY, width, dxMin, dxMax ) + + trace( 550, '\t| %s\n' % str(h) ) + trace( 550, '-' ) + return h + + + def coronaVertical ( self, chipNet, layer, chipX, width, chipYMin, chipYMax ): + trace( 550, ',+', '\tChipConf.coronaVertical\n' ) + + coronaAb = self.getInstanceAb( self.icorona ) + coronaNet = self.getCoronaNet( chipNet ) + if not coronaNet: return None + + coronaX = chipX - coronaAb.getXMin() + dyMin = ChipConf.toSymbolic( chipYMin - coronaAb.getYMin(), chip.Superior ) + dyMax = ChipConf.toSymbolic( chipYMax - coronaAb.getYMin(), chip.Inferior ) + + trace( 550, '\t| chipNet: %s %s\n' % (chipNet, layer) ) + trace( 550, '\t| Real\n' ) + trace( 550, '\t| axis: %s\n' % DbU.getValueString(coronaX) ) + trace( 550, '\t| width:%s\n' % DbU.getValueString(width) ) + + coronaX, width = self.toRoutingGauge( coronaX - width/2, coronaX + width/2, layer ) + + trace( 550, '\t| On Grid\n' ) + trace( 550, '\t| axis: %s or %s\n' % (DbU.toLambda(coronaX), DbU.getValueString(coronaX)) ) + trace( 550, '\t| width:%s or %s\n' % (DbU.toLambda(width) , DbU.getValueString(width)) ) + + v = Vertical.create( coronaNet, layer, coronaX, width, dyMin, dyMax ) + + trace( 550, '\t| %s\n' % str(v) ) + trace( 550, '-' ) + return v + + + def coronaContact ( self, chipNet, layer, chipX, chipY, width, height, flags=0 ): + trace( 550, ',+', '\tChipConf.coronaContact\n' ) + + coronaAb = self.getInstanceAb( self.icorona ) + coronaNet = self.getCoronaNet( chipNet ) + if not coronaNet: return None + + coronaX = chipX - coronaAb.getXMin() + coronaY = chipY - coronaAb.getYMin() + + trace( 550, '\t| chipNet: %s %s\n' % (chipNet, layer) ) + trace( 550, '\t| Real\n' ) + trace( 550, '\t| center: %12s %12s\n' % (DbU.getValueString(coronaX), DbU.getValueString(coronaY)) ) + trace( 550, '\t| WxH: %12s %12s\n' % (DbU.getValueString(width ), DbU.getValueString(height )) ) + + topLayer = layer.getTop() + if self.gaugeConf.isHorizontal(topLayer): + coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, layer.getBottom() ) + coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, topLayer ) + else: + coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, topLayer ) + coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, layer.getBottom() ) + + if not (flags & chip.OnHorizontalPitch): + trace( 550, '\tNot on horizontal routing pitch, Y on lambda only.\n' ) + coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), chip.Superior ) + if not (flags & chip.OnVerticalPitch ): + trace( 550, '\tNot on vertical routing pitch, X on lambda only.\n' ) + coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), chip.Superior ) + + trace( 550, '\t| On Grid\n' ) + trace( 550, '\t| X axis: %12s or %12s\n' % (DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) ) + trace( 550, '\t| Y axis: %12s or %12s\n' % (DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) ) + trace( 550, '\t| center: %12s %12s\n' % (DbU.getValueString(coronaX), DbU.getValueString(coronaY)) ) + trace( 550, '\t| WxH: %12s %12s\n' % (DbU.getValueString(width ), DbU.getValueString(height )) ) + + c = Contact.create( coronaNet + , layer + , coronaX + , coronaY + , width + , height + ) + + trace( 550, '\t| %s\n' % str(c) ) + trace( 550, '-' ) + return c + + + def coronaContactArray ( self, chipNet, layer, chipX, chipY, array, flags ): + trace( 550, ',+', '\tChipConf.coronaContactArray\n' ) + + # Should be read from the symbolic technology rules. + viaPitch = DbU.fromLambda( 4.0 ) + + coronaAb = self.getInstanceAb( self.icorona ) + coronaNet = self.getCoronaNet( chipNet ) + if not coronaNet: return None + + trace( 550, '\t| chipNet: %s %s\n' % (chipNet, layer) ) + + coronaX = chipX - coronaAb.getXMin() + coronaY = chipY - coronaAb.getYMin() + + topLayer = layer.getTop() + if self.gaugeConf.isHorizontal(topLayer): + coronaX, width = self.toRoutingGauge( coronaX, coronaX, layer.getBottom() ) + coronaY, height = self.toRoutingGauge( coronaY, coronaY, topLayer ) + else: + coronaX, width = self.toRoutingGauge( coronaX, coronaX, topLayer ) + coronaY, height = self.toRoutingGauge( coronaY, coronaY, layer.getBottom() ) + + if not (flags & chip.OnHorizontalPitch): + trace( 550, '\tNot on horizontal routing pitch, Y on lambda only.\n' ) + coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), chip.Superior ) + if not (flags & chip.OnVerticalPitch ): + trace( 550, '\tNot on vertical routing pitch, X on lambda only.\n' ) + coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), chip.Superior ) + + contacts = [] + xContact = coronaX - viaPitch * (array[0]-1)/2 + yContact = coronaY - viaPitch * (array[1]-1)/2 + contactSize = layer.getMinimalSize() + + trace( 550, '\txContact:%sl yContact:%sl\n' % (DbU.toLambda(xContact),DbU.toLambda(yContact)) ) + + for i in range(array[0]): + for j in range(array[1]): + c = Contact.create( coronaNet + , layer + , xContact + i*viaPitch + , yContact + j*viaPitch + , contactSize + , contactSize + ) + trace( 550, '\t+ %s\n' % str(c) ) + contacts.append( c ) + + trace( 550, '-' ) + return contacts + + + def coronaPin ( self, chipNet, count, direction, layer, chipX, chipY, width, height ): + trace( 550, ',+', '\tChipConf.coronaPin\n' ) + + coronaAb = self.getInstanceAb( self.icorona ) + coronaNet = self.getCoronaNet( chipNet ) + if not coronaNet: return None + + coronaX = chipX - coronaAb.getXMin() + coronaY = chipY - coronaAb.getYMin() + + trace( 550, '\t| chipNet: %s (%d) %s\n' % (chipNet, count, layer) ) + trace( 550, '\t| Real\n' ) + trace( 550, '\t| center: %s %s\n' % (DbU.getValueString(coronaX), DbU.getValueString(coronaY)) ) + trace( 550, '\t| WxH: %s %s\n' % (DbU.getValueString(width ), DbU.getValueString(height )) ) + + topLayer = layer.getTop() + if self.gaugeConf.isHorizontal(topLayer): + coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, layer.getBottom() ) + coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, topLayer ) + else: + coronaX, width = self.toRoutingGauge( coronaX - width /2, coronaX + width /2, topLayer ) + coronaY, height = self.toRoutingGauge( coronaY - height/2, coronaY + height/2, layer.getBottom() ) + + if direction == Pin.Direction.NORTH or direction == Pin.Direction.SOUTH: + trace( 550, '\tEast/West not on horizontal routing pitch, Y on lambda only.\n' ) + coronaY = self.toSymbolic( chipY - coronaAb.getYMin(), chip.Superior ) + if direction == Pin.Direction.EAST or direction == Pin.Direction.WEST: + trace( 550, '\tNorth/South not on vertical routing pitch, X on lambda only.\n' ) + coronaX = self.toSymbolic( chipX - coronaAb.getXMin(), chip.Superior ) + + trace( 550, '\t| On Grid\n' ) + trace( 550, '\t| X axis: %s or %s\n' % (DbU.toLambda(coronaY) , DbU.getValueString(coronaY)) ) + trace( 550, '\t| Y axis: %s or %s\n' % (DbU.toLambda(coronaX) , DbU.getValueString(coronaX)) ) + trace( 550, '\t| center: %s %s\n' % (DbU.getValueString(coronaX), DbU.getValueString(coronaY)) ) + trace( 550, '\t| WxH: %s %s\n' % (DbU.getValueString(width ), DbU.getValueString(height )) ) + + c = Pin.create( coronaNet + , '%s.%d' % (coronaNet.getName(),count) + , direction + , Pin.PlacementStatus.FIXED + , layer + , coronaX + , coronaY + , width + , height + ) + + trace( 550, '\t| %s\n' % str(c) ) + trace( 550, '-' ) + return c + + def checkPads ( self ): + + def contains ( padList, pad ): + for padPair in padList: + if padPair[1] == pad: return True + return False + af = CRL.AllianceFramework.get() cellPads = [] - for instance in self._cell.getInstances(): - if (af.isPad(instance.getMasterCell().getName())): - cellPads.append( instance ) + for instance in self.cell.getInstances(): + if contains(self.southPads,instance): continue + if contains(self.northPads,instance): continue + if contains(self.eastPads ,instance): continue + if contains(self.westPads ,instance): continue + if (instance.getMasterCell().getAbutmentBox().getHeight() == self.gaugeConf.getIoPadHeight()): + print ErrorMessage( 1, 'Pad "%s" is not on any side (N/S/E/W).' % instance.getName() ) + self.validated = False 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 + self.coronas.append( instance ) - 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()) ) + if len(self.coronas) > 1: + message = [ 'Chip "%s" have more than one corona:' % self.cell.getName() ] + for i in range(len(self.coronas)): + message.append( '%4d: %s' % (i,self.coronas[i].getName()) ) print ErrorMessage( 1, message ) - self._validated = False + self.validated = False + + if len(self.coronas) < 1: + print ErrorMessage( 1, 'Chip "%s" doesn\'t seems to have a corona.' % self.cell.getName() ) + self.validated = False + else: + for instance in self.corona.getInstances(): self.cores.append( instance ) + + 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 + + if len(self.cores) < 1: + print ErrorMessage( 1, 'Chip "%s" doesn\'t seems to have a core.' % self.cell.getName() ) + self.validated = False return def findPowerAndClockNets ( self ): - if self._powerPad: - for plug in self._powerPad.getPlugs(): + if self.icore: + for plug in self.icore.getPlugs(): masterNet = plug.getMasterNet() netType = masterNet.getType() - if netType != Net.Type.POWER \ + 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() ) + net = self.corona.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._clockPad.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() ) + print ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Missing global net "%s" at corona level.' + % masterNet.getName() ) self._validated = False continue - if masterNet.getName() == self._ckName: - self._guessGlobalNet( masterNet.getName(), net ) + if netType == Net.Type.GROUND: + if self.coronaVss and self.coronaVss != net: + print ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple ground nets "%s" and "%s" at corona level.' + % (self.coronaVss.getName(), net.getName()) ) + self._validated = False + continue + else: + self.coronaVss = net - for netData in ( (self._vddeName,self._vdde,'pad ring external power') - , (self._vddiName,self._vddi,'pad ring internal power') - , (self._vsseName,self._vsse,'pad ring external ground') - , (self._vssiName,self._vssi,'pad ring external ground') - , (self._ckiName ,self._cki ,'pad ring inner clock') - , (self._ckoName ,self._cko ,'core clock') - , (self._ckName ,self._ck ,'external chip clock') - ): - if not netData[1]: - print ErrorMessage( 1, 'Missing global net <%s> (%s) at chip level.' % (netData[0],netData[2]) ) - self._validated = False + if netType == Net.Type.POWER: + if self.coronaVdd and self.coronaVdd != net: + print ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple power nets "%s" and "%s" at corona level.' + % (self.coronaVdd.getName(), net.getName()) ) + self._validated = False + continue + else: + self.coronaVdd = net - self._blockageNet = self._cell.getNet(self._blockageName) - if not self._blockageNet: - self._blockageNet = Net.create( self._cell, self._blockageName ) - self._blockageNet.setType( Net.Type.BLOCKAGE ) + if netType == Net.Type.CLOCK: + if self.coronaCk and self.coronaCk != net: + print ErrorMessage( 1, 'ChipConf.findPowerAndClockNets(): Multiple clock nets "%s" and "%s" at corona level.' + % (self.coronaCk.getName(), net.getName()) ) + self._validated = False + continue + else: + self.coronaCk = net + + for net in self.corona.getNets(): + if net.getType() == Net.Type.BLOCKAGE: + self.blockageNet = net + self.blockageName = net.getName() + + if not self.blockageNet: + self.blockageNet = Net.create( self.corona, self.blockageName ) + self.blockageNet.setType( Net.Type.BLOCKAGE ) + + return + + def checkCorona ( self ): + trace( 550, ',+', 'Configuration.checkCorona()\n' ) + netPads = {} + for plug in self.icorona.getPlugs(): + padNet = plug.getNet() + coronaNet = plug.getMasterNet() + if not padNet and coronaNet.isGlobal(): + padNet = self.cell.getNet( coronaNet.getName() ) + + if padNet: + if not netPads.has_key(padNet): + trace( 550, '\t%20s <-> %-20s\n' % (padNet.getName(),coronaNet.getName()) ) + netPads[ padNet ] = coronaNet + else: + print ErrorMessage( 1, 'ChipConf.checkCorona(): Corona nets "%s" and "%s" connected to the same pad net "%s".' \ + % (coronaNet.getName(),netPads[padNet].getName(),padNet.getName()) ) + self._validated = False + + trace( 550, '-' ) return def computeChipSize ( self ): - if not self._clockPad: - print ErrorMessage( 1, 'There must be at least one pad of model "%s" to be used as reference.' \ - % self._pckName ) - self._validated = False + + def getSideLength ( pads ): + sideLength = self.gaugeConf.getIoPadHeight() * 2 + for pad in pads: sideLength += pad.getMasterCell().getAbutmentBox().getWidth() + return sideLength + + + if not self.chipSize.isEmpty(): return + + southPadsLength = getSideLength( self.southPads ) + northPadsLength = getSideLength( self.northPads ) + eastPadsLength = getSideLength( self.eastPads ) + westPadsLength = getSideLength( self.westPads ) + + horizontalPads = max( len(self.southPads), len(self.northPads) ) + verticalPads = max( len(self.eastPads ), len(self.westPads ) ) + self.chipSize = Box( 0 + , 0 + , max( southPadsLength, northPadsLength ) + , max( westPadsLength, eastPadsLength ) + ) + return + + + def setupCorona ( self, gapX1, gapY1, gapX2, gapY2 ): + ab = self.cell.getAbutmentBox() + ab.inflate ( -gapX1, -gapY1, -gapX2, -gapY2 ) + ab.inflate ( - self.getIoPadHeight() ) + ab.translate( - self.getIoPadHeight(), - self.getIoPadHeight()) + ab = self.toSymbolic( ab, chip.Inwards ) + + self. corona.setAbutmentBox( Box( 0, 0, ab.getWidth(), ab.getHeight() ) ) + self.icorona.setTransformation( + Transformation( self.toSymbolic( self.getIoPadHeight() + ab.getXMin(), chip.Superior ) + , self.toSymbolic( self.getIoPadHeight() + ab.getYMin(), chip.Superior ) + , Transformation.Orientation.ID ) ) + self.icorona.setPlacementStatus( Instance.PlacementStatus.FIXED ) + return + + + def setupCore ( self, gapX1, gapY1, gapX2, gapY2 ): + ab = self.getInstanceAb( self.icorona ) + if ab.isEmpty(): + print ErrorMessage( 1, 'ChipConf.setupCore(): Attempt to setup core *before* corona.' ) return - self._padHeight = self._clockPad.getMasterCell().getAbutmentBox().getHeight() - self._padWidth = self._clockPad.getMasterCell().getAbutmentBox().getWidth() + ab.inflate( -gapX1, -gapY1, -gapX2, -gapY2 ) + ab = self.toSymbolic( ab, chip.Inwards ) - if not self._chipSize.isEmpty(): return + trace( 550, '\tChipConf.setupCore(): Abutment box:%s\n' % str(ab) ) - 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 - ) + self.core.setAbutmentBox( Box( 0, 0, ab.getWidth(), ab.getHeight() ) ) + self.icore.setTransformation( + Transformation( ChipConf.toSymbolic(ab.getXMin(),chip.Inferior) - self.icorona.getTransformation().getTx() + , ChipConf.toSymbolic(ab.getYMin(),chip.Inferior) - self.icorona.getTransformation().getTy() + , Transformation.Orientation.ID ) ) + self.icore.setPlacementStatus( Instance.PlacementStatus.FIXED ) return - def checkChipSize ( self ): - #if self._coreSize.isEmpty(): return - # - #minWidth = self._coreSize.getWidth () + self._minCorona + 2*self._padHeight - #minHeight = self._coreSize.getHeight() + self._minCorona + 2*self._padHeight - # - #if self._chipSize.getWidth() < minWidth: - # print ErrorMessage( 1, 'Core is too wide to fit into the chip. Needs: %d, but has %d' \ - # % ( DbU.toLambda(minWidth), DbU.toLambda(self._chipSize.getWidth()) ) ) - # self._validated = False - # - #if self._chipSize.getHeight() < minHeight: - # print ErrorMessage( 1, 'Core is too wide to fit into the chip. Needs: %d, but has %d' \ - # % ( DbU.toLambda(minHeight), DbU.toLambda(self._chipSize.getHeight()) ) ) - # self._validated = False - 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 : "Configuration.ChipConfWrapper". - -class ChipConfWrapper ( GaugeConfWrapper ): - - def __init__ ( self, gaugeConf, chipConf ): - GaugeConfWrapper.__init__( self, gaugeConf ) - - #if not isinstance(chipConf,ChipConf): - # raise ErrorMessage( 1, 'Attempt to create a ChipConfWrapper() from non-ChipConf object.' ) - self._chipConf = chipConf - return - - def isValid ( self ): return self._chipConf._validated + @property + def cellGauge ( self ): return self.gaugeConf.cellGauge @property - def chipConf ( self ): return self._chipConf - - def getSliceHeight ( self ): return self._gaugeConf.getSliceHeight() - def getSliceStep ( self ): return self._gaugeConf.getSliceStep() + def routingGauge ( self ): return self.gaugeConf.routingGauge @property - def cell ( self ): return self._chipConf._cell - @property - def viewer ( self ): return self._chipConf._viewer + def verticalDepth ( self ): return self.gaugeConf.verticalDepth - # Global Pad names. @property - def pvddeckName ( self ): return self._chipConf._pvddeckName - @property - def pvsseckName ( self ): return self._chipConf._pvsseckName - @property - def pvddickName ( self ): return self._chipConf._pvddickName - @property - def pvssickName ( self ): return self._chipConf._pvssickName - @property - def pckName ( self ): return self._chipConf._pckName + def horizontalDepth ( self ): return self.gaugeConf.horizontalDepth - # Global Net names. - @property - def vddeName ( self ): return self._chipConf._vddeName - @property - def vsseName ( self ): return self._chipConf._vsseName - @property - def vddiName ( self ): return self._chipConf._vddiName - @property - def vssiName ( self ): return self._chipConf._vssiName - @property - def ckiName ( self ): return self._chipConf._ckiName - @property - def ckoName ( self ): return self._chipConf._ckoName - @property - def ckName ( self ): return self._chipConf._ckName + def getSliceHeight ( self ): return self.gaugeConf.getSliceHeight() + def getSliceStep ( self ): return self.gaugeConf.getSliceStep() + def getIoPadHeight ( self ): return self.gaugeConf.getIoPadHeight() + def getIoPadStep ( self ): return self.gaugeConf.getIoPadStep() + def getIoPadPitch ( self ): return self.gaugeConf.getIoPadPitch() + def getIoPadGauge ( self ): return self.gaugeConf.getIoPadGauge() + def getHRoutingGauge ( self ): return self.gaugeConf.getHRoutingGauge() + def getVRoutingGauge ( self ): return self.gaugeConf.getVRoutingGauge() - # Global Nets. - @property - def vdde ( self ): return self._chipConf._vdde - @property - def vsse ( self ): return self._chipConf._vsse - @property - def vddi ( self ): return self._chipConf._vddi - @property - def vssi ( self ): return self._chipConf._vssi - @property - def cki ( self ): return self._chipConf._cki - @property - def cko ( self ): return self._chipConf._cko - @property - def ck ( self ): return self._chipConf._ck - @property - def blockageNet ( self ): return self._chipConf._blockageNet + def rpByOccurrence ( self, occurrence, net ): + return self.gaugeConf._rpByOccurrence ( occurrence, net ) - # Various. - @property - def clockPad ( self ): return self._chipConf._clockPad - @property - def powerPad ( self ): return self._chipConf._powerPad - @property - def cores ( self ): return self._chipConf._cores - @property - def southPads ( self ): return self._chipConf._southPads - @property - def northPads ( self ): return self._chipConf._northPads - @property - def eastPads ( self ): return self._chipConf._eastPads - @property - def westPads ( self ): return self._chipConf._westPads - @property - def coreSize ( self ): return self._chipConf._coreSize - @coreSize.setter - def coreSize ( self, ab ): self._chipConf._coreSize = ab - @property - def chipSize ( self ): return self._chipConf._chipSize - @property - def minCorona ( self ): return self._chipConf._minCorona - @property - def padWidth ( self ): return self._chipConf._padWidth - @property - def padHeight ( self ): return self._chipConf._padHeight - @property - def useClockTree ( self ): return self._chipConf._useClockTree + def rpByPlugName ( self, instance, plugName, net ): + return self.gaugeConf._rpByPlugName ( instance, plugName, net ) + + def rpAccess ( self, rp, flags=0 ): + return self.gaugeConf._rpAccess( rp, flags ) + + def rpAccessByOccurrence ( self, occurrence, net, flags=0 ): + return self.gaugeConf._rpAccessByOccurrence ( occurrence, net, flags ) + + def rpAccessByPlugName ( self, instance, plugName, net, flags=0 ): + return self.gaugeConf._rpAccessByPlugName( instance, plugName, net, flags ) + + def createContact ( self, net, x, y, flags=0 ): + return self.gaugeConf._createContact( net, x, y, flags ) + + def createHorizontal ( self, source, target, y, flags=0 ): + return self.gaugeConf._createHorizontal( source, target, y, flags ) + + def createVertical ( self, source, target, x, flags=0 ): + return self.gaugeConf._createVertical( source, target, x, flags ) + + def getNearestHorizontalTrack ( self, bb, y, flags ): + return self.gaugeConf._getNearestHorizontalTrack ( bb, y, flags ) + + def getNearestVerticalTrack ( self, bb, x, flags ): + return self.gaugeConf._getNearestVerticalTrack( bb, x, flags ) + + def setStackPosition ( self, topContact, x, y ): + self.gaugeConf._setStackPosition( topContact, x, y ) def loadConfiguration ( cell, viewer=None ): sys.path.append( os.getcwd() ) - confFile = cell.getName()+'_chip' + confFile = cell.getName()+'_ioring' if not os.path.isfile(confFile+'.py'): raise ErrorMessage( 1, 'ChipPlugin configuration file <%s.py> is missing.' % confFile ) @@ -809,5 +1103,4 @@ def loadConfiguration ( cell, viewer=None ): raise WarningMessage( 'Module <%s> do not provides the chip variable, skipped.' \ % confFile ) - return ChipConfWrapper( GaugeConf() - , ChipConf ( confModule.__dict__['chip'], cell, viewer ) ) + return ChipConf( confModule.__dict__['chip'], cell, viewer ) diff --git a/cumulus/src/plugins/chip/PadsCorona.py b/cumulus/src/plugins/chip/PadsCorona.py index a6fc3f01..961f70b7 100644 --- a/cumulus/src/plugins/chip/PadsCorona.py +++ b/cumulus/src/plugins/chip/PadsCorona.py @@ -20,70 +20,215 @@ import Cfg from Hurricane import DbU from Hurricane import Point from Hurricane import Transformation +from Hurricane import Interval from Hurricane import Box from Hurricane import Path from Hurricane import Occurrence from Hurricane import UpdateSession +from Hurricane import Layer +from Hurricane import BasicLayer from Hurricane import Net +from Hurricane import Pin from Hurricane import Contact +from Hurricane import Segment from Hurricane import Horizontal from Hurricane import Vertical from Hurricane import Instance import CRL -from CRL import RoutingLayerGauge +from CRL import RoutingLayerGauge from helpers import trace from helpers import ErrorMessage from helpers import WarningMessage import chip.Configuration -class Side ( object ): +class Corner ( 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 ) + def __init__ ( self, corona, cornerType ): + self.type = cornerType + self.corona = corona + self.padCorner = None return - def _toGrid ( self, v ): return v - (v % self._corona.getSliceStep()) + def _getPoints ( self, axis ): + if self.type == chip.SouthWest: + xCorner = self.corona.conf.chipSize.getXMin() + axis + yCorner = self.corona.conf.chipSize.getYMin() + axis + xBb = self.corona.conf.chipSize.getXMin() + self.corona.conf.getIoPadHeight() + yBb = self.corona.conf.chipSize.getYMin() + self.corona.conf.getIoPadHeight() + elif self.type == chip.SouthEast: + xCorner = self.corona.conf.chipSize.getXMax() - axis + yCorner = self.corona.conf.chipSize.getYMin() + axis + xBb = self.corona.conf.chipSize.getXMax() - self.corona.conf.getIoPadHeight() + yBb = self.corona.conf.chipSize.getYMin() + self.corona.conf.getIoPadHeight() + elif self.type == chip.NorthEast: + xCorner = self.corona.conf.chipSize.getXMax() - axis + yCorner = self.corona.conf.chipSize.getYMax() - axis + xBb = self.corona.conf.chipSize.getXMax() - self.corona.conf.getIoPadHeight() + yBb = self.corona.conf.chipSize.getYMax() - self.corona.conf.getIoPadHeight() + elif self.type == chip.NorthWest: + xCorner = self.corona.conf.chipSize.getXMin() + axis + yCorner = self.corona.conf.chipSize.getYMax() - axis + xBb = self.corona.conf.chipSize.getXMin() + self.corona.conf.getIoPadHeight() + yBb = self.corona.conf.chipSize.getYMax() - self.corona.conf.getIoPadHeight() + + return xCorner, yCorner, xBb, yBb + + + def _createCorner ( self ): + for rail in self.corona.padRails: + net = rail[0] + layer = rail[1] + axis = rail[2] + width = rail[3] + + xCorner, yCorner, xBb, yBb = self._getPoints( axis ) + + Contact .create( net, layer, xCorner, yCorner, width, width ) + Horizontal.create( net, layer, yCorner, width, xCorner, xBb ) + Vertical .create( net, layer, xCorner, width, yCorner, yBb ) + return + + + def _getTransformation ( self ): + if self.type == chip.SouthWest: + name = 'padcorner_sw' + x = self.corona.conf.chipSize.getXMin() + y = self.corona.conf.chipSize.getYMin() + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.ID + else: + orientation = Transformation.Orientation.R1 + x += self.padCorner.getAbutmentBox().getWidth() + + elif self.type == chip.SouthEast: + name = 'padcorner_se' + x = self.corona.conf.chipSize.getXMax() + y = self.corona.conf.chipSize.getYMin() + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.R1 + else: + orientation = Transformation.Orientation.R2 + x += self.padCorner.getAbutmentBox().getWidth() + y += self.padCorner.getAbutmentBox().getHeight() + + elif self.type == chip.NorthEast: + name = 'padcorner_ne' + x = self.corona.conf.chipSize.getXMax() + y = self.corona.conf.chipSize.getYMax() + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.R2 + else: + orientation = Transformation.Orientation.R3 + x -= self.padCorner.getAbutmentBox().getwidth() + y -= self.padCorner.getAbutmentBox().getHeight() + + elif self.type == chip.NorthWest: + name = 'padcorner_nw' + x = self.corona.conf.chipSize.getXMin() + y = self.corona.conf.chipSize.getYMax() + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.R3 + else: + orientation = Transformation.Orientation.ID + y -= self.padCorner.getAbutmentBox().getHeight() + + return name, Transformation( self.corona.toGrid(x), self.corona.toGrid(y), orientation ) + + + def _instanciateCorner ( self ): + name, transformation = self._getTransformation() + + corner = Instance.create( self.corona.conf.cell + , name, self.corona.padCorner + , transformation + , Instance.PlacementStatus.FIXED + ) + return + + + def doLayout ( self ): + if self.corona.padCorner: self._instanciateCorner() + else: self._createCorner() + return + + +class Side ( object ): + + def __init__ ( self, corona, sideType ): + self.type = sideType + self.corona = corona + self.pins = [] + self.u = self.corona.conf.getIoPadHeight() + self.spacerCount = 0 + self.gap = 0 + + if self.type == chip.North: + self.pads = self.corona.conf.northPads + self.sideName = 'north' + self.sideLength = self.corona.conf.chipSize.getWidth() + + elif self.type == chip.South: + self.pads = self.corona.conf.southPads + self.sideName = 'south' + self.sideLength = self.corona.conf.chipSize.getWidth() + + elif self.type == chip.East: + self.pads = self.corona.conf.eastPads + self.sideName = 'east' + self.sideLength = self.corona.conf.chipSize.getHeight() + + elif self.type == chip.West: + self.pads = self.corona.conf.westPads + self.sideName = 'west' + self.sideLength = self.corona.conf.chipSize.getHeight() + + else: + raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) + + self.spacerNames = 'padspacer_' + self.sideName + '_%d' + return + + + def toGrid ( self, u ): return self.corona.toGrid( u ) def getAxis ( self, i ): - if self._type == chip.North: return self._corona.chipSize.getYMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.South: return self._corona.chipSize.getYMin() + self._corona.padHeight - self._corona._powerRails[i][2] - elif self._type == chip.East: return self._corona.chipSize.getXMax() - self._corona.padHeight + self._corona._powerRails[i][2] - elif self._type == chip.West: return self._corona.chipSize.getXMin() + self._corona.padHeight - self._corona._powerRails[i][2] + if self.type == chip.North: return self.corona.conf.chipSize.getYMax() - self.corona.conf.getIoPadHeight() + self.corona.powerRails[i][2] + elif self.type == chip.South: return self.corona.conf.chipSize.getYMin() + self.corona.conf.getIoPadHeight() - self.corona.powerRails[i][2] + elif self.type == chip.East: return self.corona.conf.chipSize.getXMax() - self.corona.conf.getIoPadHeight() + self.corona.powerRails[i][2] + elif self.type == chip.West: return self.corona.conf.chipSize.getXMin() + self.corona.conf.getIoPadHeight() - self.corona.powerRails[i][2] else: raise ErrorMessage( 1, 'PadsCorona.Side.__init__(): Invalid value for sideType (%d)' % sideType ) return 0 + def hasPad ( self, padInstance ): + for pad in self.pads: + if pad[1] == padInstance: + return True + return False + + def _check ( self, checkSize, checkName ): sideName = 'unknown' chipSize = 0 - if self._type == chip.North or self._type == chip.South: - chipSize = self._corona.chipSize.getWidth() + if self.type == chip.North or self.type == chip.South: + chipSize = self.corona.conf.chipSize.getWidth() sideName = 'wide' - elif self._type == chip.East or self._type == chip.West: - chipSize = self._corona.chipSize.getHeight() + elif self.type == chip.East or self.type == chip.West: + chipSize = self.corona.conf.chipSize.getHeight() sideName = 'tall' if checkSize > chipSize: - sliceHeight = self._corona.getSliceHeight() + sliceHeight = self.corona.conf.getSliceHeight() if checkSize % sliceHeight != 0: checkSize += sliceHeight - (checkSize % sliceHeight) 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) ) + , 'needs %s, but only has %s.' + % ( DbU.getValueString(checkSize), DbU.getValueString(chipSize) ) ] ) return False return True @@ -91,343 +236,908 @@ class Side ( object ): def check ( self ): self.validated = True - if self._type == chip.North: - self.validated = self._check( self._corona.coreSize.getWidth() - + 2*self._corona.minCorona - + 2*self._corona.padHeight + if self.type == chip.North: + #print DbU.getValueString(self.corona.conf.coreSize.getWidth()) + #print DbU.getValueString(self.corona.conf.minCorona) + #print DbU.getValueString(self.corona.conf.getIoPadHeight()) + self.validated = self._check( self.corona.conf.coreSize.getWidth() + + 2*self.corona.conf.minCorona + + 2*self.corona.conf.getIoPadHeight() , '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 + elif self.type == chip.East: + self.validated = self._check( self.corona.conf.coreSize.getHeight() + + 2*self.corona.conf.minCorona + + 2*self.corona.conf.getIoPadHeight() , 'core' ) checkName = 'east pads' - elif self._type == chip.South: checkName = 'south pads' - elif self._type == chip.West: checkName = 'west pads' + elif self.type == chip.South: checkName = 'south pads' + elif self.type == chip.West: checkName = 'west pads' - self.validated = self._check( len(self._pads) * self._corona.padWidth - + 2*self._corona.padHeight - , checkName ) and self.validated + #self.validated = self._check( len(self.pads) * self.corona.conf.padWidth + # + 2*self.corona.conf.padHeight + # , checkName ) and self.validated return self.validated - def _createPowerContacts ( self, pad, net ): - if self._type == chip.North or self._type == chip.South: - hvDepth = self._corona.padVDepth - elif self._type == chip.East or self._type == chip.West: - hvDepth = self._corona.padHDepth +# def _createPowerContacts ( self, pad, net ): +# if self._type == chip.North or self._type == chip.South: +# hvDepth = self._corona.padVDepth +# elif self._type == chip.East or self._type == chip.West: +# hvDepth = self._corona.padHDepth +# +# trace( 550, ',+', '\t_createPowerContacts() for %s\n' % net.getName() ) +# +# components = None +# masterCell = pad.getMasterCell() +# trace( 550, '\tLooking for global net %s\n' % net.getName() ) +# for plug in net.getPlugs(): +# if plug.getInstance() == pad: +# trace( 550, '\tFound Plug on %s\n' % pad ) +# components = plug.getMasterNet().getExternalComponents() +# if not components: +# masterNet = masterCell.getNet( net.getName() ) +# if masterNet: +# components = masterCell.getNet(net.getName()).getExternalComponents() +# if not components: +# raise ErrorMessage( 1, [ 'PadsCorona.Side._createPowerContact():' +# , 'Pad model <%s> of instance <%s> neither have global net <%s>' % (pad.getName(),masterCell.getName(),net.getName()) +# , 'for implicit connection nor is it explicitly connected.' +# , 'The power/clock nets *names* in the chip must match those of the pads models.' +# ] ) +# +# +# connecteds = False +# trace( 550, '\t %s\n' % str(masterCell.getAbutmentBox()) ) +# for component in components: +# 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 ) +# +# connecteds = True +# self._powerContacts.append( Contact.create( net +# , component.getLayer() +# , position.getX() +# , position.getY() +# , width +# , height +# ) ) +# if not connecteds: +# print WarningMessage( 'Cannot find a suitable connector for <%s> on pad <%s>' +# % (net.getName(),pad.getName()) ) +# +# trace( 550, '-' ) +# return - trace( 550, ',+', '\t_createPowerContacts() for %s\n' % net.getName() ) - components = None - masterCell = pad.getMasterCell() - trace( 550, '\tLooking for global net %s\n' % net.getName() ) - for plug in net.getPlugs(): - if plug.getInstance() == pad: - trace( 550, '\tFound Plug on %s\n' % pad ) - components = plug.getMasterNet().getExternalComponents() - if not components: - masterNet = masterCell.getNet( net.getName() ) - if masterNet: - components = masterCell.getNet(net.getName()).getExternalComponents() - if not components: - raise ErrorMessage( 1, [ 'PadsCorona.Side._createPowerContact():' - , 'Pad model <%s> of instance <%s> neither have global net <%s>' % (pad.getName(),masterCell.getName(),net.getName()) - , 'for implicit connection nor is it explicitly connected.' - , 'The power/clock nets *names* in the chip must match those of the pads models.' - ] ) - +# def _createAllPowerContacts ( self ): +# for pad in self.pads: +# masterCell = pad.getMasterCell() +# if masterCell.getName() != self._corona.pvddickName \ +# and masterCell.getName() != self._corona.pvssickName \ +# and masterCell.getName() != self._corona.pvddeckName \ +# and masterCell.getName() != self._corona.pvsseckName: +# continue +# #print 'Power pad:', pad +# self._createPowerContacts( pad, self._corona.vddi ) +# self._createPowerContacts( pad, self._corona.vssi ) +# if self._corona.useClockTree: +# self._createPowerContacts( pad, self._corona.cko ) +# return - connecteds = False - trace( 550, '\t %s\n' % str(masterCell.getAbutmentBox()) ) - for component in components: - 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() + def _fillPadSpacing ( self, gapWidth ): + if not self.corona.padSpacers: + self.u += gapWidth + return + + iPadSpacer = 0 - position = Point( component.getX(), masterCell.getAbutmentBox().getYMin() ) - pad.getTransformation().applyOn( position ) + def _getWidth ( spacer ): return spacer.getAbutmentBox().getWidth() + def _nextSpacer ( iPadSpacer ): + while iPadSpacer < len(self.corona.padSpacers) \ + and gapWidth < _getWidth(self.corona.padSpacers[iPadSpacer]): + iPadSpacer += 1 + return iPadSpacer - connecteds = True - self._powerContacts.append( Contact.create( net - , component.getLayer() - , position.getX() - , position.getY() - , width - , height - ) ) - if not connecteds: - print WarningMessage( 'Cannot find a suitable connector for <%s> on pad <%s>' - % (net.getName(),pad.getName()) ) + iPadSpacer = _nextSpacer( iPadSpacer ) - trace( 550, '-' ) + while iPadSpacer < len(self.corona.padSpacers) and gapWidth > 0: + gapWidth -= _getWidth( self.corona.padSpacers[iPadSpacer] ) + spacer = Instance.create( self.corona.conf.cell + , self.spacerNames % self.spacerCount + , self.corona.padSpacers[iPadSpacer]) + self.spacerCount += 1 + self._placePad( spacer ) + + if gapWidth < _getWidth(self.corona.padSpacers[iPadSpacer]): + iPadSpacer = _nextSpacer( iPadSpacer ) + + if gapWidth != 0: + print ErrorMessage( 1, 'PadsCorona.Side._placePads(): Pad fillers cannot close the gap between pads on %s side, %s remains.' \ + % (self.sideName,DbU.getValueString(gapWidth)) ) + + self.u += gapWidth return - def _createAllPowerContacts ( self ): - for pad in self._pads: - masterCell = pad.getMasterCell() - if masterCell.getName() != self._corona.pvddickName \ - and masterCell.getName() != self._corona.pvssickName \ - and masterCell.getName() != self._corona.pvddeckName \ - and masterCell.getName() != self._corona.pvsseckName: - continue - #print 'Power pad:', pad - self._createPowerContacts( pad, self._corona.vddi ) - self._createPowerContacts( pad, self._corona.vssi ) - if self._corona.useClockTree: - self._createPowerContacts( pad, self._corona.cko ) + def _placePad ( self, padInstance ): + if self.type == chip.North: + x = self.corona.conf.chipSize.getXMin() + self.u + y = self.corona.conf.chipSize.getYMax() + + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.MY + else: + orientation = Transformation.Orientation.ID + y -= self.corona.conf.getIoPadHeight() + + elif self.type == chip.South: + x = self.corona.conf.chipSize.getXMin() + self.u + y = self.corona.conf.chipSize.getYMin() + + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.ID + else: + orientation = Transformation.Orientation.MY + y += self.corona.conf.getIoPadHeight() + + elif self.type == chip.West: + x = self.corona.conf.chipSize.getXMin() + y = self.corona.conf.chipSize.getYMin() + self.u + + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.R3 + y += padInstance.getMasterCell().getAbutmentBox().getWidth() + else: + orientation = Transformation.Orientation.R1 + x += padInstance.getMasterCell().getAbutmentBox().getHeight() + + elif self.type == chip.East: + x = self.corona.conf.chipSize.getXMax() + y = self.corona.conf.chipSize.getYMin() + self.u + + if self.corona.padOrient == Transformation.Orientation.ID: + orientation = Transformation.Orientation.R1 + else: + orientation = Transformation.Orientation.R3 + x -= padInstance.getMasterCell().getAbutmentBox().getHeight() + y += padInstance.getMasterCell().getAbutmentBox().getWidth() + + padInstance.setTransformation ( Transformation( self.toGrid(x), self.toGrid(y), orientation ) ) + padInstance.setPlacementStatus( Instance.PlacementStatus.FIXED ) + + self.u += padInstance.getMasterCell().getAbutmentBox().getWidth() 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 + padLength = 0 + for pad in self.pads: padLength += pad[1].getMasterCell().getAbutmentBox().getWidth() + padSpacing = (self.sideLength - 2*self.corona.conf.getIoPadHeight() - padLength) / (len(self.pads) + 1) - 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 + if self.corona.conf.padsHavePosition: + for i in range(len(self.pads)): + self.pads[i][0] = self.toGrid( self.pads[i][0] ) + else: + position = self.u + for i in range(len(self.pads)): + position += padSpacing + self.pads[i][0] = self.toGrid( position ) + position += self.pads[i][1].getMasterCell().getAbutmentBox().getWidth() + + for pad in self.pads: + self._fillPadSpacing( pad[0] - self.u ) + self._placePad( pad[1] ) + + self._fillPadSpacing( self.sideLength - self.corona.conf.getIoPadHeight() - self.u ) + + return + + + def _getUMin ( self, box ): + if self.type == chip.North or self.type == chip.South: + return box.getXMin() + return box.getYMin() + + + def _getUMax ( self, box ): + if self.type == chip.North or self.type == chip.South: + return box.getXMax() + return box.getYMax() + + + def _createSegment ( self, rail, uMin, uMax ): + net, layer, axis, width = rail + if self.corona.conf.getIoPadGauge().getName() == 'pxlib': + if net.isClock(): + uMin -= DbU.fromLambda(5.0) + uMax += DbU.fromLambda(5.0) + else: + uMin -= width/2 + uMax += width/2 + + if self.type == chip.North or self.type == chip.South: + if self.type == chip.North: + axis = self.corona.conf.chipSize.getYMax() - axis + Horizontal.create( net, layer, axis, width, uMin, uMax ) + else: + if self.type == chip.East: + axis = self.corona.conf.chipSize.getXMax() - axis + Vertical.create( net, layer, axis, width, uMin, uMax ) 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] - ) + if self.type == chip.South or self.type == chip.North: + startCorner = self.corona.conf.chipSize.getXMin() + stopCorner = self.corona.conf.chipSize.getXMax() + elif self.type == chip.West or self.type == chip.East: + startCorner = self.corona.conf.chipSize.getYMin() + stopCorner = self.corona.conf.chipSize.getYMax() + else: + return + + startCorner += self.corona.conf.getIoPadHeight() + stopCorner -= self.corona.conf.getIoPadHeight() + + if len(self.pads) == 0: + return + + padAb = self.corona.conf.getInstanceAb( self.pads[0][1] ) + for irail in range(len(self.corona.padRails)): + self._createSegment( self.corona.padRails[ irail ] + , startCorner + , self._getUMin(padAb) ) + + padAb = self.corona.conf.getInstanceAb( self.pads[-1][1] ) + for irail in range(len(self.corona.padRails)): + self._createSegment( self.corona.padRails[ irail ] + , self._getUMax(padAb) + , stopCorner ) + + for i in range(len(self.pads)-1): + padAb1 = self.corona.conf.getInstanceAb( self.pads[i ][1] ) + padAb2 = self.corona.conf.getInstanceAb( self.pads[i+1][1] ) + + for rail in self.corona.padRails: + self._createSegment( rail, self._getUMax(padAb1), self._getUMin(padAb2) ) + return + def doLayout ( self ): self._placePads() - self._routePads() - self._createAllPowerContacts() + if not self.corona.padSpacers: + self._routePads() + #self._createAllPowerContacts() return -class Corona ( chip.Configuration.ChipConfWrapper ): +class CoreWire ( object ): - def __init__ ( self, conf ): - chip.Configuration.ChipConfWrapper.__init__( self, conf.gaugeConf, conf.chipConf ) - 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] ] + # Should be read from the symbolic technology rules. + viaPitch = DbU.fromLambda( 4.0 ) - self._locatePadRails() - self._guessPadHvLayers() + def __init__ ( self, corona, chipNet, padSegment, bbSegment, side, preferredDir, count ): + self.corona = corona + self.chipNet = chipNet + self.padSegment = padSegment + self.bbSegment = bbSegment + self.side = side + self.preferredDir = preferredDir + self.arraySize = None + self.count = count 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 - @property - def padHDepth ( self ): return self._horizontalPadDepth - @property - def padVDepth ( self ): return self._verticalPadDepth - 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 _computeCoreLayers ( self ): + rg = self.corona.conf.gaugeConf.routingGauge + mask = self.padSegment.getLayer().getMask() + + self.symSegmentLayer = None + for layerGauge in rg.getLayerGauges(): + if layerGauge.getLayer().getMask() == mask: + self.symSegmentLayer = layerGauge.getLayer() + + if self.preferredDir: + self.symContactLayer = self.symSegmentLayer + if self.side & (chip.West|chip.East): + self.symContactSize = ( layerGauge.getWireWidth(), self.bbSegment.getHeight() ) + else: + self.symContactSize = ( self.bbSegment.getWidth(), layerGauge.getWireWidth() ) + else: + depth = layerGauge.getDepth() + if layerGauge.getDepth() + 1 >= rg.getDepth(): + self.symSegmentLayer = rg.getLayerGauge( depth-1 ).getLayer() + depth -= 1 + else: + self.symSegmentLayer = rg.getLayerGauge( depth+1 ).getLayer() + + self.symContactLayer = rg.getContactLayer( depth ) + self.symContactSize = ( self.bbSegment.getWidth(), self.bbSegment.getWidth() ) + + contactMinSize = 2*self.symContactLayer.getEnclosure( self.symSegmentLayer.getBasicLayer() + , Layer.EnclosureH|Layer.EnclosureV ) \ + + self.symContactLayer.getMinimalSize() + + arrayWidth = (self.bbSegment.getWidth() - contactMinSize) / CoreWire.viaPitch + trace( 550, '\tcontactMinSize: %sl, width: %sl, arrayWidth: %d\n' + % (DbU.toLambda(contactMinSize),DbU.toLambda(self.bbSegment.getWidth()),arrayWidth) ) + if arrayWidth < 0: arrayWidth = 0 + if arrayWidth < 3: + if self.side & (chip.North|chip.South): + self.arraySize = ( arrayWidth+1, 2 ) + else: + self.arraySize = ( 2, arrayWidth+1 ) + + trace( 550, '\tarraySize = (%d,%d)\n' % (self.arraySize[0], self.arraySize[1]) ) + return + + print ErrorMessage( 1, 'CoreWire._computeCoreLayers(): Layer of IO pad segment "%s" is not in routing gauge.' \ + % self.chipNet.getName() ) + + return + + + def drawWire ( self ): + trace( 550, ',+', '\tCoreWire.drawWire(): chip:"%s"\n' %(self.chipNet.getName()) ) + + coreAb = self.corona.conf.getInstanceAb( self.corona.conf.icorona ) + + self._computeCoreLayers() + + padLayer = self.padSegment.getLayer() + if not isinstance(padLayer,BasicLayer): + padLayer = padLayer.getBasicLayer() + + if self.side == chip.West or self.side == chip.East: + flags = chip.OnHorizontalPitch + + if self.side == chip.West: + accessDirection = Pin.Direction.WEST + xPadMin = self.bbSegment.getXMin() + xContact = self.corona.coreSymBb.getXMin() + xPadMax = xContact + xCore = coreAb.getXMin() + if not self.preferredDir: + xPadMax += self.bbSegment.getHeight()/2 + else: + accessDirection = Pin.Direction.EAST + xPadMax = self.bbSegment.getXMax() + xContact = self.corona.coreSymBb.getXMax() + xPadMin = xContact + xCore = coreAb.getXMax() + if not self.preferredDir: + xPadMin -= self.bbSegment.getHeight()/2 + + hReal = Horizontal.create( self.chipNet + , self.padSegment.getLayer() + , self.bbSegment.getCenter().getY() + , self.bbSegment.getHeight() + , xPadMin + , xPadMax + ) + trace( 550, '\tself.arraySize: %s\n' % str(self.arraySize) ) + if self.arraySize: + contacts = self.corona.conf.coronaContactArray( self.chipNet + , self.symContactLayer + , xContact + , self.bbSegment.getCenter().getY() + , self.arraySize + , flags + ) + vStrapBb = Box() + for contact in contacts: + vStrapBb.merge( contact.getBoundingBox() ) + else: + contact = self.corona.conf.coronaContact( self.chipNet + , self.symContactLayer + , xContact + , self.bbSegment.getCenter().getY() + , self.symContactSize[0] + , self.symContactSize[1] + , flags + ) + vStrapBb = contact.getBoundingBox( padLayer ) + + hRealBb = hReal.getBoundingBox( padLayer ) + self.corona.conf.icorona.getTransformation().applyOn( vStrapBb ) + vStrapBb.merge( vStrapBb.getXMin(), hRealBb.getYMin() ) + vStrapBb.merge( vStrapBb.getXMin(), hRealBb.getYMax() ) + if self.padSegment.getLayer().isSymbolic(): + vStrapBb.inflate( 0, -self.padSegment.getLayer().getExtentionCap() + , 0, -self.padSegment.getLayer().getExtentionCap() ) + + Vertical.create( self.chipNet + , self.padSegment.getLayer() + , vStrapBb.getCenter().getX() + , vStrapBb.getWidth() + , vStrapBb.getYMin() + , vStrapBb.getYMax() + ) + + if self.arraySize: + if self.side == chip.West: xContact = min( xContact, vStrapBb.getXMin() ) + else: xContact = max( xContact, vStrapBb.getXMax() ) + + self.corona.conf.coronaHorizontal( self.chipNet + , self.symSegmentLayer + , self.bbSegment.getCenter().getY() + , self.bbSegment.getHeight() + , xContact + , xCore + ) + trace( 550, '\tCORONA PIN: %s %d\n' % (self.chipNet, self.count) ) + pin = self.corona.conf.coronaPin( self.chipNet + , self.count + , accessDirection + , self.symSegmentLayer + , xCore + , self.bbSegment.getCenter().getY() + , DbU.fromLambda( 1.0 ) + , self.bbSegment.getHeight() + ) + else: + flags = chip.OnVerticalPitch + + if self.side == chip.South: + accessDirection = Pin.Direction.SOUTH + yPadMin = self.bbSegment.getYMin() + yPadMax = self.corona.coreSymBb.getYMin() + yContact = yPadMax + yCore = coreAb.getYMin() + if not self.preferredDir: + yPadMax += self.bbSegment.getWidth()/2 + else: + accessDirection = Pin.Direction.NORTH + yPadMax = self.bbSegment.getYMax() + yPadMin = self.corona.coreSymBb.getYMax() + yContact = yPadMin + yCore = coreAb.getYMax() + if not self.preferredDir: + yPadMin -= self.bbSegment.getWidth()/2 + + vReal = Vertical.create( self.chipNet + , self.padSegment.getLayer() + , self.bbSegment.getCenter().getX() + , self.bbSegment.getWidth() + , yPadMin + , yPadMax + ) + trace( 550, '\tself.arraySize: %s\n' % str(self.arraySize) ) + if self.arraySize: + contacts = self.corona.conf.coronaContactArray( self.chipNet + , self.symContactLayer + , self.bbSegment.getCenter().getX() + , yContact + , self.arraySize + , flags + ) + hStrapBb = Box() + for contact in contacts: + hStrapBb.merge( contact.getBoundingBox() ) + else: + contact = self.corona.conf.coronaContact( self.chipNet + , self.symContactLayer + , self.bbSegment.getCenter().getX() + , yContact + , self.symContactSize[0] + , self.symContactSize[1] + , flags + ) + hStrapBb = contact.getBoundingBox( padLayer ) + + vRealBb = vReal.getBoundingBox() + self.corona.conf.icorona.getTransformation().applyOn( hStrapBb ) + hStrapBb.merge( vRealBb.getXMin(), hStrapBb.getYMin() ) + hStrapBb.merge( vRealBb.getXMax(), hStrapBb.getYMin() ) + if self.padSegment.getLayer().isSymbolic(): + hStrapBb.inflate( -self.padSegment.getLayer().getExtentionCap(), 0 + , -self.padSegment.getLayer().getExtentionCap(), 0 ) + + Horizontal.create( self.chipNet + , self.padSegment.getLayer() + , hStrapBb.getCenter().getY() + , hStrapBb.getHeight() + , hStrapBb.getXMin() + , hStrapBb.getXMax() + ) + + if self.arraySize: + if self.side == chip.South: yContact = min( yContact, hStrapBb.getYMin() ) + else: yContact = max( yContact, hStrapBb.getYMax() ) + + self.corona.conf.coronaVertical( self.chipNet + , self.symSegmentLayer + , self.bbSegment.getCenter().getX() + , self.bbSegment.getWidth() + , yContact + , yCore + ) + pin = self.corona.conf.coronaPin( self.chipNet + , self.count + , accessDirection + , self.symSegmentLayer + , self.bbSegment.getCenter().getX() + , yCore + , self.bbSegment.getWidth() + , DbU.fromLambda( 1.0 ) + ) + + if self.side & chip.North: self.corona.northSide.pins.append( pin ) + if self.side & chip.South: self.corona.southSide.pins.append( pin ) + if self.side & chip.East : self.corona.eastSide .pins.append( pin ) + if self.side & chip.West : self.corona.westSide .pins.append( pin ) + + trace( 550, '-' ) + return + + +class Corona ( object ): + + + def __init__ ( self, conf ): + def _cmpPad ( pad1, pad2): + width1 = pad1.getAbutmentBox().getWidth() + width2 = pad2.getAbutmentBox().getWidth() + if width1 == width2: return 0 + if width1 > width2: return -1 + return 1 + + self.conf = 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 : Corner( self, chip.SouthWest ) + , chip.SouthEast : Corner( self, chip.SouthEast ) + , chip.NorthWest : Corner( self, chip.NorthWest ) + , chip.NorthEast : Corner( self, chip.NorthEast ) + } + self.padLib = None + self.padOrient = Transformation.Orientation.ID + self.padSpacers = [] + self.padCorner = [] + self.padRails = [] # [ , [net, layer, axis, width] ] + + if Cfg.hasParameter('chip.padCoreSide'): + if Cfg.getParamString('chip.padCoreSide').asString().lower() == 'south': + self.padOrient = Transformation.Orientation.MY + + self._allPadsAnalysis() + if Cfg.hasParameter('chip.padSpacers'): + for spacerName in Cfg.getParamString('chip.padSpacers').asString().split(','): + spacerCell = self.padLib.getCell( spacerName ) + if spacerCell: self.padSpacers.append( spacerCell ) + else: + print ErrorMessage( 1, 'Corona.__init__(): Missing spacer cell "%s"' % spacerName ) + self.padSpacers.sort( _cmpPad ) + + if Cfg.hasParameter('chip.padCorner'): + self.padCorner = self.padLib.getCell( Cfg.getParamString('chip.padCorner').asString() ) + + return + + + def toGrid ( self, u ): return u - (u % self.conf.getIoPadPitch()) 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 + self._allPadsAnalysis() + 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 "%s" to guess the pad rails.' \ - % self.pckName ) - return False + def hasNorthPad ( self, padInstance ): return self.northSide.hasPad(padInstance) + def hasSouthPad ( self, padInstance ): return self.southSide.hasPad(padInstance) + def hasEastPad ( self, padInstance ): return self.eastSide.hasPad(padInstance) + def hasWestPad ( self, padInstance ): return self.westSide.hasPad(padInstance) - 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: + def hasPad ( self, padInstance ): + if self.hasNorthPad(padInstance): return True + if self.hasSouthPad(padInstance): return True + if self.hasEastPad (padInstance): return True + if self.hasWestPad (padInstance): return True + return False + + + def _allPadsAnalysis ( self ): + for pad in self.conf.southPads: + self._padAnalysis( pad[1] ) + if self.padRails: return + + for pad in self.conf.northPads: + self._padAnalysis( pad[1] ) + if self.padRails: return + + for pad in self.conf.eastPads: + self._padAnalysis( pad[1] ) + if self.padRails: return + + for pad in self.conf.westPads: + self._padAnalysis( pad[1] ) + if self.padRails: return + + return + + + def _padAnalysis ( self, padInstance ): + if self.padRails: return + + padCell = padInstance.getMasterCell() + ab = padCell.getAbutmentBox() + + if not self.padLib: self.padLib = padCell.getLibrary() + + for plug in padInstance.getPlugs(): + for component in plug.getMasterNet().getComponents(): + if isinstance(component,Horizontal): + hspan = Interval( component.getBoundingBox().getXMin() + , component.getBoundingBox().getXMax() ) + + # Specific hack for Alliance pxlib pad library. + if self.conf.getIoPadGauge().getName() == 'pxlib': + if plug.getMasterNet().isClock(): + hspan.inflate( DbU.fromLambda(5.0) ) + else: + hspan.inflate( component.getWidth() / 2 ) + + if hspan.contains( ab.getXMin() ) or hspan.contains( ab.getXMax() ): + duplicate = False + + if self.padOrient == Transformation.Orientation.ID: + axis = component.getY() + else: + axis = self.conf.getIoPadHeight() - component.getY() + + for rail in self.padRails: + if rail[0] == plug.getNet() \ + and rail[1] == component.getLayer() \ + and rail[2] == axis: + duplicate = True + break + + if not duplicate: + net = plug.getNet() + if not net: + if plug.getMasterNet().isGlobal(): + net = self.conf.cell.getNet( plug.getMasterNet().getName() ) + if not net: + print ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is not connected and there is no global net (in pad \"%s").' \ + % plug.getMasterNet().getName(), padCell.getName() ) + else: + print ErrorMessage( 1, 'PadsCorona._padAnalysis(): Ring net "%s" is neither connected nor global (in pad \"%s").' \ + % plug.getMasterNet().getName(), padCell.getName() ) + + if net: + self.padRails.append( ( net + , component.getLayer() + , axis + , component.getWidth() ) ) + return + + + def _createCoreWire ( self, chipIntNet, padNet, padInstance, count ): + padSide = None + if self.hasSouthPad(padInstance): padSide = chip.South + elif self.hasNorthPad(padInstance): padSide = chip.North + elif self.hasEastPad (padInstance): padSide = chip.East + elif self.hasWestPad (padInstance): padSide = chip.West + if not padSide: return None + + innerBb = self.conf.cell.getAbutmentBox().inflate( -self.conf.getIoPadHeight() ) + rg = self.conf.gaugeConf.routingGauge + hsegments = { } + vsegments = { } + for component in padNet.getExternalComponents(): + if isinstance(component,Segment): + bb = component.getBoundingBox() + padInstance.getTransformation().applyOn( bb ) + if bb.intersect(innerBb): + lg = rg.getLayerGauge( component.getLayer() ) + depth = lg.getDepth() + if lg.getDirection() == RoutingLayerGauge.Vertical: + if not vsegments.has_key(depth): vsegments[ depth ] = [] + vsegments[ depth ].append( (component,bb) ) + else: + if not hsegments.has_key(depth): hsegments[ depth ] = [] + hsegments[ depth ].append( (component,bb) ) + + gapWidth = 0 + segments = None + inPreferredDir = False + if padSide == chip.North or padSide == chip.South: + if len(vsegments): + inPreferredDir = True + segments = vsegments[ min(vsegments.keys()) ] + elif len(hsegments): + segments = hsegments[ min(hsegments.keys()) ] + gapWidth = bb.getWidth() + trace( 550, '\tNorth/South but RDir H, gapWidth: %s\n' % DbU.getValueString(gapWidth) ) + else: + if len(hsegments): + inPreferredDir = True + segments = hsegments[ min(hsegments.keys()) ] + elif len(vsegments): + segments = vsegments[ min(vsegments.keys()) ] + gapWidth = bb.getWidth() + trace( 550, '\tEast/West but RDir V, gapWidth: %s\n' % DbU.getValueString(gapWidth) ) + + coreWires = [] + if segments: + for segment, bb in segments: + if padSide == chip.South: self.southSide.gap = max( self.southSide.gap, gapWidth ) + elif padSide == chip.North: self.northSide.gap = max( self.northSide.gap, gapWidth ) + elif padSide == chip.East : self.eastSide.gap = max( self.eastSide.gap , gapWidth ) + elif padSide == chip.West : self.westSide.gap = max( self.westSide.gap , gapWidth ) + + coreWires.append( CoreWire( self, chipIntNet, segment, bb, padSide, inPreferredDir, count ) ) + count += 1 + return coreWires + + + def _placeInnerCorona ( self ): + rg = self.conf.gaugeConf.routingGauge + + coronaSouthGap = 0 + for layerGauge in rg.getLayerGauges(): + self.southSide.gap = max( self.southSide.gap, layerGauge.getPitch() * 2 ) + self.northSide.gap = self.southSide.gap + self.eastSide.gap = self.southSide.gap + self.westSide.gap = self.southSide.gap + + coreWires = [] + + for coronaPlug in self.conf.icorona.getPlugs(): + chipIntNet = coronaPlug.getNet() + if not chipIntNet: + print ErrorMessage( 1, 'PadsCorona._placeInnerCorona(): Corona net "%s" is not connected to a pad.' \ + % coronaPlug.getMasterNet().getName() ) 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 + padConnected = 0 + doneInstances = [] + for chipPlug in chipIntNet.getPlugs(): + doneInstances.append( chipPlug.getInstance() ) + padNet = chipPlug.getMasterNet() + padWires = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected ) + if padWires: + coreWires += padWires + padConnected += len(padWires) - 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 + if chipIntNet.isGlobal(): + for instance in self.conf.cell.getInstances(): + if instance in doneInstances: continue + doneInstances.append( instance ) + + padNet = instance.getMasterCell().getNet( chipIntNet.getName() ) + if not padNet: continue - self._powerRails.append( [ net, component.getLayer(), component.getY(), component.getWidth() ] ) + padWires = self._createCoreWire( chipIntNet, padNet, doneInstances[-1], padConnected ) + if padWires: + coreWires += padWires + padConnected += len(padWires) - self._powerRails.sort( key=itemgetter(2) ) + if padConnected == 0: + print ErrorMessage( 1, 'PadsCorona._placeInnerCorona(): Chip net "%s" is not connected to a pad.' \ + % chipIntNet.getName() ) + + self.conf.setupCorona( self.westSide.gap, self.southSide.gap, self.eastSide.gap, self.northSide.gap ) + + self.coreSymBb = self.conf.getInstanceAb( self.conf.icorona ) + self.coreSymBb.inflate( self.conf.toSymbolic( self.westSide.gap /2, chip.Superior ) + , self.conf.toSymbolic( self.southSide.gap/2, chip.Superior ) + , self.conf.toSymbolic( self.eastSide.gap /2, chip.Inferior ) + , self.conf.toSymbolic( self.northSide.gap/2, chip.Inferior ) ) + + for wire in coreWires: + trace( 550, '\t| %s %d %s\n' % (wire.chipNet.getName(),wire.count,wire.padSegment.getLayer())) + + for wire in coreWires: wire.drawWire() - #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 _guessPadHvLayers ( self ): - if not self.powerPad: - print ErrorMessage( 1, 'There must be at least one pad of model "%s" to guess the pad power terminals.' \ - % self.pvddick ) - 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._horizontalPadDepth = 0 - self._verticalPadDepth = 0 - for depth in range(0,self.topLayerDepth+1): - if not depth in availableDepths: continue - - if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: - self._horizontalPadDepth = depth - if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: - self._verticalPadDepth = depth - - #print 'h:', self._horizontalPadDepth - #print 'v:', self._verticalPadDepth - return +# def _locatePadRails ( self ): +# if not self.clockPad: +# print ErrorMessage( 1, 'There must be at least one pad of model "%s" to guess the pad rails.' \ +# % self.pckName ) +# 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 _guessPadHvLayers ( self ): +# if not self.powerPad: +# print ErrorMessage( 1, 'There must be at least one pad of model "%s" to guess the pad power terminals.' \ +# % self.pvddick ) +# 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._horizontalPadDepth = 0 +# self._verticalPadDepth = 0 +# for depth in range(0,self.topLayerDepth+1): +# if not depth in availableDepths: continue +# +# if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Horizontal: +# self._horizontalPadDepth = depth +# if self.routingGauge.getLayerGauge(depth).getDirection() == RoutingLayerGauge.Vertical: +# self._verticalPadDepth = depth +# +# #print 'h:', self._horizontalPadDepth +# #print 'v:', self._verticalPadDepth +# return def doLayout ( self ): if not self.validated: return UpdateSession.open() - self.cell.setAbutmentBox( self.chipSize ) + self.conf.cell.setAbutmentBox( self.conf.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) + for corner in self.corners.values(): + corner.doLayout() - 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() + self.northSide.doLayout() + self.southSide.doLayout() + self.eastSide.doLayout() + self.westSide.doLayout() + self._placeInnerCorona() UpdateSession.close() return diff --git a/cumulus/src/plugins/chip/__init__.py b/cumulus/src/plugins/chip/__init__.py index 8155c0e9..ff95dea8 100644 --- a/cumulus/src/plugins/chip/__init__.py +++ b/cumulus/src/plugins/chip/__init__.py @@ -17,13 +17,20 @@ # Common constants used through all modules. # For Corona's sides. -North = 0000 -South = 0001 -East = 0002 -West = 0003 +North = 0x0001 +South = 0x0002 +East = 0x0004 +West = 0x0008 # For Corona's corners. -SouthWest = 0000 -SouthEast = 0001 -NorthWest = 0002 -NorthEast = 0003 +SouthWest = South|West +SouthEast = South|East +NorthWest = North|West +NorthEast = North|East + +# For rounding functions. +Superior = 0x0010 +Inferior = 0x0020 +Inwards = 0x0040 +OnHorizontalPitch = 0x0080 +OnVerticalPitch = 0x0100 diff --git a/cumulus/src/plugins/clocktree/ClockTree.py b/cumulus/src/plugins/clocktree/ClockTree.py index 1808e352..df01e822 100755 --- a/cumulus/src/plugins/clocktree/ClockTree.py +++ b/cumulus/src/plugins/clocktree/ClockTree.py @@ -42,20 +42,14 @@ try: import helpers from helpers import trace from helpers import ErrorMessage - #import Nimbus - #import Metis - #import Mauka - import Katabatic - import Kite import Unicorn import plugins from clocktree.RSMT import RSMT + from chip.Configuration import GaugeConf from chip.Configuration import getPlugByNet from chip.Configuration import getPlugByName from chip.Configuration import getRpBb from chip.Configuration import destroyNetComponents - from chip.Configuration import GaugeConf - from chip.Configuration import GaugeConfWrapper except ImportError, e: serror = str(e) if serror.startswith('No module named'): @@ -75,7 +69,7 @@ except Exception, e: sys.exit(2) -class HTree ( GaugeConfWrapper ): +class HTree ( object ): @staticmethod def create ( conf, cell, clockNet, clockBox ): @@ -99,7 +93,7 @@ class HTree ( GaugeConfWrapper ): return ht def __init__ ( self, conf, cell, clockNet, area ): - GaugeConfWrapper.__init__( self, conf.gaugeConf ) + self.conf = conf self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt() ) if self.minSide < DbU.fromLambda(100.0): @@ -113,7 +107,6 @@ class HTree ( GaugeConfWrapper ): self.childs = [] self._getBufferIo() self.tieCell = self.framework.getCell( 'rowend_x0', CRL.Catalog.State.Views ) - self.cellGauge = self.framework.getCellGauge() self.topBuffer = Instance.create( self.cell, 'ck_htree', self.bufferCell ) self.cloneds = [ self.cell ] self.usedVTracks = [] @@ -160,8 +153,8 @@ class HTree ( GaugeConfWrapper ): self._feedCount += 1 return self._feedCount - def toXCellGrid ( self, x ): return x - (x % self.cellGauge.getSliceStep ()) - def toYCellGrid ( self, y ): return y - (y % self.cellGauge.getSliceHeight()) + def toXCellGrid ( self, x ): return x - (x % self.conf.cellGauge.getSliceStep ()) + def toYCellGrid ( self, y ): return y - (y % self.conf.cellGauge.getSliceHeight()) def rpDistance ( self, rp1, rp2 ): dx = abs( rp1.getX() - rp2.getX() ) @@ -173,9 +166,9 @@ class HTree ( GaugeConfWrapper ): yslice = self.toYCellGrid(y) transformation = Transformation.Orientation.ID - if ((yslice-self.area.getYMin()) / self.cellGauge.getSliceHeight()) % 2 != 0: + if ((yslice-self.area.getYMin()) / self.conf.cellGauge.getSliceHeight()) % 2 != 0: transformation = Transformation.Orientation.MY - yslice += self.cellGauge.getSliceHeight() + yslice += self.conf.cellGauge.getSliceHeight() instance.setTransformation ( Transformation(xslice, yslice, transformation) ) instance.setPlacementStatus( Instance.PlacementStatus.FIXED ) @@ -193,7 +186,7 @@ class HTree ( GaugeConfWrapper ): , 'htree_feed_%i' % self.feedCounter() , self.tieCell , Transformation(x,transformation.getTy(),transformation.getOrientation()) - #, Instance.PlacementStatus.PLACED + , Instance.PlacementStatus.PLACED ) x += tieWidth return @@ -267,16 +260,16 @@ class HTree ( GaugeConfWrapper ): if not node.component: x = node.realX if node.realX in self.usedVTracks: - x += self.routingGauge.getLayerGauge(self.verticalDeepDepth).getPitch() + x += self.conf.routingGauge.getLayerGauge(self.conf.verticalDeepDepth).getPitch() # This is a Steiner point. - node.component = self.createContact( net - , x - , node.y + self.cellGauge.getSliceHeight()/2 - self.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch() - , GaugeConf.DeepDepth ) + node.component = self.conf.createContact( net + , x + , node.y + self.conf.cellGauge.getSliceHeight()/2 - self.conf.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch() + , GaugeConf.DeepDepth ) trace( 550, '\tCreate (Steiner) node.component: @Y%d (y:%d - %d) %s\n' \ % (DbU.toLambda(node.realY) ,DbU.toLambda(node.y) - ,DbU.toLambda(self.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch()) + ,DbU.toLambda(self.conf.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch()) ,node.component) ) else: # This a terminal (graph) point @@ -289,7 +282,7 @@ class HTree ( GaugeConfWrapper ): flags |= GaugeConf.OffsetTop1 if node.realX in self.usedVTracks: flags |= GaugeConf.OffsetRight1 - node.component = self.rpAccess( node.component, flags ) + node.component = self.conf.rpAccess( node.component, flags ) for edge in mst.edges: sourceContact = edge.source.component @@ -300,12 +293,12 @@ class HTree ( GaugeConfWrapper ): elif edge.isVertical(): self.createVertical ( sourceContact, targetContact, sourceContact.getX(), GaugeConf.DeepDepth ) else: - turn = self.createContact( edge.source.component.getNet() - , sourceContact.getX() - , targetContact.getY() - , GaugeConf.DeepDepth ) - self.createVertical ( sourceContact, turn, sourceContact.getX(), GaugeConf.DeepDepth ) - self.createHorizontal( turn, targetContact, targetContact.getY(), GaugeConf.DeepDepth ) + turn = self.conf.createContact( edge.source.component.getNet() + , sourceContact.getX() + , targetContact.getY() + , GaugeConf.DeepDepth ) + self.conf.createVertical ( sourceContact, turn, sourceContact.getX(), GaugeConf.DeepDepth ) + self.conf.createHorizontal( turn, targetContact, targetContact.getY(), GaugeConf.DeepDepth ) return def _connectLeafs ( self, leafBuffer, leafs ): @@ -512,8 +505,8 @@ class HTreeNode ( object ): self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight ) self.topTree.usedVTracks += \ - [ self.topTree.rpAccessByPlugName( self.blBuffer, self.topTree.bufferIn, self.ckNet ).getX() - , self.topTree.rpAccessByPlugName( self.brBuffer, self.topTree.bufferIn, self.ckNet ).getX() ] + [ self.topTree.conf.rpAccessByPlugName( self.blBuffer, self.topTree.bufferIn, self.ckNet ).getX() + , self.topTree.conf.rpAccessByPlugName( self.brBuffer, self.topTree.bufferIn, self.ckNet ).getX() ] for child in self.childs: child.place() return @@ -521,42 +514,42 @@ class HTreeNode ( object ): def route ( self ): trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() ) - leftSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) - rightSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) - blContact = self.topTree.rpAccessByPlugName( self.blBuffer , self.topTree.bufferIn , self.ckNet ) - brContact = self.topTree.rpAccessByPlugName( self.brBuffer , self.topTree.bufferIn , self.ckNet ) - tlContact = self.topTree.rpAccessByPlugName( self.tlBuffer , self.topTree.bufferIn , self.ckNet ) - trContact = self.topTree.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet ) - leftContact = self.topTree.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() ) - rightContact = self.topTree.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() ) + leftSourceContact = self.topTree.conf.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) + rightSourceContact = self.topTree.conf.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) + blContact = self.topTree.conf.rpAccessByPlugName( self.blBuffer , self.topTree.bufferIn , self.ckNet ) + brContact = self.topTree.conf.rpAccessByPlugName( self.brBuffer , self.topTree.bufferIn , self.ckNet ) + tlContact = self.topTree.conf.rpAccessByPlugName( self.tlBuffer , self.topTree.bufferIn , self.ckNet ) + trContact = self.topTree.conf.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet ) + leftContact = self.topTree.conf.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() ) + rightContact = self.topTree.conf.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() ) - leftSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftSourceContact.getX(), 0 ) - leftSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, leftSourceContact.getY(), 0 ) - rightSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightSourceContact.getX(), 0 ) - rightSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, rightSourceContact.getY(), 0 ) - leftX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftContact.getX(), 0 ) - rightX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightContact.getX(), 0 ) - tlY = self.topTree.getNearestHorizontalTrack( self.topTree.area, tlContact.getY(), 0 ) - blY = self.topTree.getNearestHorizontalTrack( self.topTree.area, blContact.getY(), 0 ) + leftSourceX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, leftSourceContact.getX(), 0 ) + leftSourceY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, leftSourceContact.getY(), 0 ) + rightSourceX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, rightSourceContact.getX(), 0 ) + rightSourceY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, rightSourceContact.getY(), 0 ) + leftX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, leftContact.getX(), 0 ) + rightX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, rightContact.getX(), 0 ) + tlY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, tlContact.getY(), 0 ) + blY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, blContact.getY(), 0 ) - self.topTree.setStackPosition( leftSourceContact, leftSourceX, leftSourceY ) - self.topTree.setStackPosition( rightSourceContact, rightSourceX, rightSourceY ) - self.topTree.setStackPosition( tlContact, leftX, tlY ) - self.topTree.setStackPosition( blContact, leftX, blY ) - self.topTree.setStackPosition( trContact, rightX, tlY ) - self.topTree.setStackPosition( brContact, rightX, blY ) + self.topTree.conf.setStackPosition( leftSourceContact, leftSourceX, leftSourceY ) + self.topTree.conf.setStackPosition( rightSourceContact, rightSourceX, rightSourceY ) + self.topTree.conf.setStackPosition( tlContact, leftX, tlY ) + self.topTree.conf.setStackPosition( blContact, leftX, blY ) + self.topTree.conf.setStackPosition( trContact, rightX, tlY ) + self.topTree.conf.setStackPosition( brContact, rightX, blY ) leftContact .setX( leftX ) leftContact .setY( leftSourceY ) rightContact.setX( rightX ) rightContact.setY( rightSourceY ) - self.topTree.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 ) - self.topTree.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 ) - self.topTree.createVertical ( leftContact , blContact , leftX , 0 ) - self.topTree.createVertical ( tlContact , leftContact , leftX , 0 ) - self.topTree.createVertical ( rightContact , brContact , rightX , 0 ) - self.topTree.createVertical ( trContact , rightContact , rightX , 0 ) + self.topTree.conf.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 ) + self.topTree.conf.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 ) + self.topTree.conf.createVertical ( leftContact , blContact , leftX , 0 ) + self.topTree.conf.createVertical ( tlContact , leftContact , leftX , 0 ) + self.topTree.conf.createVertical ( rightContact , brContact , rightX , 0 ) + self.topTree.conf.createVertical ( trContact , rightContact , rightX , 0 ) for child in self.childs: child.route() return diff --git a/katana/src/NegociateWindow.cpp b/katana/src/NegociateWindow.cpp index 10f32206..24243551 100644 --- a/katana/src/NegociateWindow.cpp +++ b/katana/src/NegociateWindow.cpp @@ -325,6 +325,7 @@ namespace Katana { autoSegment->getConstraints( constraints ); uside.intersection( constraints ); + cdebug_log(159,0) << "* Constraints " << constraints << endl; cdebug_log(159,0) << "* Nearest " << track << endl; if (not track) diff --git a/katana/src/PowerRails.cpp b/katana/src/PowerRails.cpp index a3957548..bb6a8b53 100644 --- a/katana/src/PowerRails.cpp +++ b/katana/src/PowerRails.cpp @@ -107,252 +107,130 @@ namespace { bool isCoreClockNetRouted ( const Net* ) const; inline Cell* getTopCell () const; Net* getRootNet ( const Net*, Path ) const; - inline Net* getVdde () const; - inline Net* getVddi () const; - inline Net* getVsse () const; - inline Net* getVssi () const; + inline Net* getVdd () const; + inline Net* getVss () const; inline Net* getCk () const; - inline Net* getCki () const; - inline Net* getCko () const; inline Net* getBlockage () const; inline void setBlockage ( Net* ); private: bool guessGlobalNet ( const Name&, Net* ); private: uint32_t _flags; - Name _vddePadNetName; - Name _vddiPadNetName; - Name _vssePadNetName; - Name _vssiPadNetName; - Name _ckPadNetName; - Name _ckiPadNetName; - Name _ckoPadNetName; - Net* _vdde; - Net* _vddi; - Net* _vsse; - Net* _vssi; - Net* _ck; // Clock net on the (external) pad. - Net* _cki; // Clock net in the pad ring. - Net* _cko; // Clock net of the core (design). + Name _vddCoreName; + Name _vssCoreName; + Name _ckCoreName; + Net* _vdd; + Net* _vss; + Net* _ck; Net* _blockage; Cell* _topCell; }; inline Cell* GlobalNetTable::getTopCell () const { return _topCell; } - inline Net* GlobalNetTable::getVdde () const { return _vdde; } - inline Net* GlobalNetTable::getVddi () const { return _vddi; } - inline Net* GlobalNetTable::getVsse () const { return _vsse; } - inline Net* GlobalNetTable::getVssi () const { return _vssi; } + inline Net* GlobalNetTable::getVdd () const { return _vdd; } + inline Net* GlobalNetTable::getVss () const { return _vss; } inline Net* GlobalNetTable::getCk () const { return _ck; } - inline Net* GlobalNetTable::getCki () const { return _cki; } - inline Net* GlobalNetTable::getCko () const { return _cko; } inline Net* GlobalNetTable::getBlockage () const { return _blockage; } inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; } GlobalNetTable::GlobalNetTable ( KatanaEngine* katana ) - : _flags (0) - , _vddePadNetName("vdde") - , _vddiPadNetName("vddi") - , _vssePadNetName("vsse") - , _vssiPadNetName("vssi") - , _ckPadNetName ("pad" ) - , _ckiPadNetName ("ck" ) - , _ckoPadNetName ("cko" ) - , _vdde (NULL) - , _vddi (NULL) - , _vsse (NULL) - , _vssi (NULL) - , _ck (NULL) - , _cki (NULL) - , _cko (NULL) - , _blockage(NULL) - , _topCell (katana->getCell()) + : _flags (0) + , _vddCoreName() + , _vssCoreName() + , _ckCoreName () + , _vdd (NULL) + , _vss (NULL) + , _ck (NULL) + , _blockage (NULL) + , _topCell (katana->getCell()) { if (_topCell == NULL) return; cmess1 << " o Looking for powers/grounds & clocks." << endl; - AllianceFramework* af = AllianceFramework::get(); + for( Net* net : _topCell->getNets() ) { + Net::Type netType = net->getType(); - bool hasPad = false; - for( Instance* instance : _topCell->getInstances() ) { - if (af->isPad(instance->getMasterCell())) { - if (not hasPad) { - cmess1 << " o Design has pads, assuming complete chip top structure." << endl; - hasPad = true; - } + if (netType == Net::Type::CLOCK) { + if (not net->isExternal()) continue; - string padName = getString( instance->getMasterCell()->getName() ); - if (padName.substr(0,8) == "pvddeck_") { - cmess1 << " o Reference power pad: " << instance->getName() - << "(model:" << instance->getMasterCell()->getName() << ")." << endl; - - // Guessing the power, ground and clock nets from *this* pad connexions. - for( Plug* plug : instance->getPlugs() ) { - Net* masterNet = plug->getMasterNet(); - Net::Type netType = masterNet->getType(); - if ( (netType != Net::Type::POWER ) - and (netType != Net::Type::GROUND) - and (netType != Net::Type::CLOCK ) ) continue; - - Net* net = plug->getNet(); - if (not net) { - net = _topCell->getNet( masterNet->getName() ); - if (not net) { - cerr << Error("Missing global net <%s> at chip level.",getString(masterNet->getName()).c_str()) << endl; - continue; - } - } - - guessGlobalNet( masterNet->getName(), net ); + if (_ckCoreName.isEmpty()) { + cmess1 << " - Using <" << net->getName() << "> as internal (core) clock net." << endl; + _ckCoreName = net->getName(); + _ck = net; + if (NetRoutingExtension::isMixedPreRoute(net)) { + cmess1 << " (core clock net is already routed)" << endl; + _flags |= ClockIsRouted; + } else { + cmess1 << " (core clock net will be routed as an ordinary signal)" << endl; } + } else { + cerr << Error("Second clock net <%s> net at top block level will be ignored.\n" + " (will consider only <%s>)" + , getString(net->getName()).c_str() + , getString(_ck->getName()).c_str() + ) << endl; } + } - padName = getString( instance->getMasterCell()->getName() ); - if (padName.substr(0,4) == "pck_") { - cmess1 << " o Reference clock pad: " << instance->getName() - << "(model:" << instance->getMasterCell()->getName() << ")." << endl; + if (NetRoutingExtension::isManualGlobalRoute(net)) continue; - // Guessing external clock net *only* from *this* pad connexions. - for( Plug* plug : instance->getPlugs() ) { - Net* masterNet = plug->getMasterNet(); - Net* net = plug->getNet(); - if (not net) { - net = _topCell->getNet( masterNet->getName() ); - if (not net) { - cerr << Error("Missing global net <%s> at chip level.",getString(masterNet->getName()).c_str()) << endl; - continue; - } - } + if (netType == Net::Type::POWER) { + if (_vddCoreName.isEmpty()) { + _vddCoreName = net->getName(); + _vdd = net; + } else { + cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n" + " (will consider only <%s>)" + , getString(net ->getName()).c_str() + , getString(_vdd->getName()).c_str() + ) << endl; + } + } - if (masterNet->getName() == _ckPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as external chip clock net." << endl; - _ck = net; - } - } + if (netType == Net::Type::GROUND) { + if (_vssCoreName.isEmpty()) { + _vssCoreName = net->getName(); + _vss = net; + } else { + cerr << Error("Second power ground net <%s> net at top block level will be ignored.\n" + " (will consider only <%s>)" + , getString(net ->getName()).c_str() + , getString(_vss->getName()).c_str() + ) << endl; } } } + + if (_vdd == NULL) cerr << Error("Missing POWER net at top block level." ) << endl; + else destroyRing( _vdd ); + if (_vss == NULL) cerr << Error("Missing GROUND net at top block level." ) << endl; + else destroyRing( _vss ); - if (hasPad) { - if (_vdde == NULL) cerr << Error("Missing net (for pads) at chip level." ) << endl; - else destroyRing( _vdde ); - if (_vsse == NULL) cerr << Error("Missing net (for pads) at chip level." ) << endl; - else destroyRing( _vsse ); - if (_vddi == NULL) cerr << Error("Missing / net (for pads) at top level." ) << endl; - else destroyRing( _vddi ); - if (_vssi == NULL) cerr << Error("Missing / net (for pads) at top level." ) << endl; - else destroyRing( _vssi ); - if (_ck == NULL) cerr << Warning("No net at (for pads) chip level." ) << endl; - if (_cki == NULL) cerr << Warning("No net at (for pads) chip level." ) << endl; - else destroyRing( _cki ); - } else { - _vddiPadNetName = ""; - _vssiPadNetName = ""; - _ckoPadNetName = ""; - - for( Net* net : _topCell->getNets() ) { - Net::Type netType = net->getType(); - - if (netType == Net::Type::CLOCK) { - if (not net->isExternal()) continue; - - if (_ckoPadNetName.isEmpty()) { - cmess1 << " - Using <" << net->getName() << "> as internal (core) clock net." << endl; - _ckoPadNetName = net->getName(); - _cko = net; - if (NetRoutingExtension::isMixedPreRoute(net)) { - cmess1 << " (core clock net is already routed)" << endl; - _flags |= ClockIsRouted; - } else { - cmess1 << " (core clock net will be routed as an ordinary signal)" << endl; - } - } else { - cerr << Error("Second clock net <%s> net at top block level will be ignored.\n" - " (will consider only <%s>)" - , getString(net ->getName()).c_str() - , getString(_cko->getName()).c_str() - ) << endl; - } - } - - if (NetRoutingExtension::isManualGlobalRoute(net)) continue; - - if (netType == Net::Type::POWER) { - if (_vddiPadNetName.isEmpty()) { - _vddiPadNetName = net->getName(); - _vddi = net; - } else { - cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n" - " (will consider only <%s>)" - , getString(net ->getName()).c_str() - , getString(_vddi->getName()).c_str() - ) << endl; - } - } - - if (netType == Net::Type::GROUND) { - if (_vssiPadNetName.isEmpty()) { - _vssiPadNetName = net->getName(); - _vssi = net; - } else { - cerr << Error("Second power ground net <%s> net at top block level will be ignored.\n" - " (will consider only <%s>)" - , getString(net ->getName()).c_str() - , getString(_vssi->getName()).c_str() - ) << endl; - } - } - } - - if (_vddi == NULL) cerr << Error("Missing net at top block level." ) << endl; - else destroyRing( _vddi ); - if (_vssi == NULL) cerr << Error("Missing net at top block level." ) << endl; - else destroyRing( _vssi ); - } - - if (_cko == NULL) cparanoid << Warning("No clock net at top level." ) << endl; + if (_ck == NULL) cparanoid << Warning("No CLOCK net at top level." ) << endl; } bool GlobalNetTable::guessGlobalNet ( const Name& name, Net* net ) { - if (name == _vddePadNetName) { - cmess1 << " - Using <" << net->getName() << "> as corona (external:vdde) power net." << endl; - _vdde = net; + if (name == _vddCoreName) { + cmess1 << " - Using <" << net->getName() << "> as core (internal:vdd) power net." << endl; + _vdd = net; return true; } - if (name == _vddiPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as core (internal:vddi) power net." << endl; - _vddi = net; + if (name == _vssCoreName) { + cmess1 << " - Using <" << net->getName() << "> as core (internal:vss) ground net." << endl; + _vss = net; return true; } - if (name == _vssePadNetName) { - cmess1 << " - Using <" << net->getName() << "> as corona (external:vsse) ground net." << endl; - _vsse = net; - return true; - } + if (name == _ckCoreName) { + cmess1 << " - Using <" << net->getName() << "> as core (internal:ck) clock net." << endl; + _ck = net; - if (name == _vssiPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as core (internal:vssi) ground net." << endl; - _vssi = net; - return true; - } - - if (name == _ckiPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as corona (external:cki) clock net." << endl; - _cki = net; - return true; - } - - if (name == _ckoPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as core (internal:cko) clock net." << endl; - _cko = net; - - if (NetRoutingExtension::isMixedPreRoute(_cko)) { + if (NetRoutingExtension::isMixedPreRoute(_ck)) { cmess1 << " (core clock net is already routed)" << endl; _flags |= ClockIsRouted; } else { @@ -361,12 +239,6 @@ namespace { return true; } - if (name == _ckPadNetName) { - cmess1 << " - Using <" << net->getName() << "> as external chip clock net." << endl; - _ck = net; - return true; - } - return false; } @@ -377,11 +249,8 @@ namespace { if (net == _blockage) return _blockage; - if (_vdde and (net->getName() == _vdde->getName())) return _vdde; - if (_vsse and (net->getName() == _vsse->getName())) return _vsse; - - if (net->getType() == Net::Type::POWER ) return _vddi; - if (net->getType() == Net::Type::GROUND) return _vssi; + if (net->getType() == Net::Type::POWER ) return _vdd; + if (net->getType() == Net::Type::GROUND) return _vss; if (net->getType() != Net::Type::CLOCK ) { return NULL; } @@ -420,17 +289,12 @@ namespace { } } - cdebug_log(159,0) << " Check againts top clocks ck:" << ((_ck) ? _ck->getName() : "NULL") - << " cki:" << ((_cki) ? _cki->getName() : "NULL") - << " cko:" << ((_cko) ? _cko->getName() : "NULL") - << endl; + cdebug_log(159,0) << " Check againts top clocks ck:" + << ((_ck) ? _ck->getName() : "NULL") << endl; - if (_ck and (upNet->getName() == _ck->getName() )) return _ck; - if (_cki and (upNet->getName() == _cki->getName())) return _cki; - - if (_cko) { - if (upNet->getName() == _cko->getName()) { - if (isCoreClockNetRouted(upNet)) return _cko; + if (_ck) { + if (upNet->getName() == _ck->getName()) { + if (isCoreClockNetRouted(upNet)) return _ck; } } @@ -439,7 +303,7 @@ namespace { bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const - { return (net == _cko) and (_flags & ClockIsRouted); } + { return (net == _ck) and (_flags & ClockIsRouted); } // ------------------------------------------------------------------- @@ -1076,7 +940,7 @@ namespace { QueryPowerRails::QueryPowerRails ( KatanaEngine* katana ) : Query () , _framework (AllianceFramework::get()) - , _katana (katana) + , _katana (katana) , _routingGauge (katana->getConfiguration()->getRoutingGauge()) , _chipTools (katana->getChipTools()) , _powerRailsPlanes(katana) @@ -1086,7 +950,7 @@ namespace { , _goMatchCount (0) { setCell ( katana->getCell() ); - setArea ( katana->getCell()->getBoundingBox() ); + setArea ( katana->getCell()->getAbutmentBox() ); setBasicLayer ( NULL ); setFilter ( Query::DoTerminalCells|Query::DoComponents ); diff --git a/katana/src/PreProcess.cpp b/katana/src/PreProcess.cpp index 67d103ff..4c230688 100644 --- a/katana/src/PreProcess.cpp +++ b/katana/src/PreProcess.cpp @@ -270,9 +270,13 @@ namespace { TrackElement* segment = track->getSegment(i); if (not segment or segment->isRouted()) continue; if (segment and segment->isFixed() and segment->isTerminal()) { - Interval freeInterval = track->getFreeInterval( segment->getSourceU(), segment->getNet() ); - DbU::Unit ppitch = segment->getPPitch(); - //DbU::Unit pitch = segment->getPitch(); + DbU::Unit ppitch = segment->getPPitch(); + //DbU::Unit pitch = segment->getPitch(); + + if ( ((segment->getSourceU() - track->getMin()) < 2*ppitch) + or ((track->getMax() - segment->getTargetU()) < 2*ppitch) ) continue; + + Interval freeInterval = track->getFreeInterval( segment->getSourceU(), segment->getNet() ); //if (freeInterval.getSize() < ppitch*6) { if ( (segment->getSourceU() - freeInterval.getVMin() < ppitch*3) diff --git a/katana/src/PreRouteds.cpp b/katana/src/PreRouteds.cpp index 57c1f404..587c4200 100644 --- a/katana/src/PreRouteds.cpp +++ b/katana/src/PreRouteds.cpp @@ -24,12 +24,6 @@ #include "katana/KatanaEngine.h" -namespace { - - -} // Anonymous namespace. - - namespace Katana { using namespace std;