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).
This commit is contained in:
Jean-Paul Chaput 2019-05-10 11:58:05 +02:00
parent ce60ed5a30
commit 82dc58bf8e
23 changed files with 2426 additions and 1381 deletions

View File

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

View File

@ -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<Horizontal*>(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<Vertical*>(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<Contact*>(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<Contact*>( isegment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( isegment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment );
for ( auto segment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, segment );
autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet );
}
}

View File

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

View File

@ -1,6 +1,7 @@
# -*- Mode:Python; explicit-buffer-name: "plugins.conf<cmos>" -*-
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')

View File

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

View File

@ -154,7 +154,6 @@ namespace CRL {
AllianceFramework* af = AllianceFramework::get();
pitch = af->getCellGauge()->getPitch();
size_t count = 0;
UpdateSession::open ();
unique_ptr<Bookshelf::Circuit> 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 );

View File

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

View File

@ -1,27 +1,29 @@
# -*- explicit-buffer-name: "CMakeLists.txt<cumulus/src>" -*-
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 )

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,13 +17,20 @@
# Common constants used through all <chip> 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

View File

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

View File

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

View File

@ -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 <vdde> net (for pads) at chip level." ) << endl;
else destroyRing( _vdde );
if (_vsse == NULL) cerr << Error("Missing <vsse> net (for pads) at chip level." ) << endl;
else destroyRing( _vsse );
if (_vddi == NULL) cerr << Error("Missing <vddi>/<vdd> net (for pads) at top level." ) << endl;
else destroyRing( _vddi );
if (_vssi == NULL) cerr << Error("Missing <vssi>/<vss> net (for pads) at top level." ) << endl;
else destroyRing( _vssi );
if (_ck == NULL) cerr << Warning("No <ck> net at (for pads) chip level." ) << endl;
if (_cki == NULL) cerr << Warning("No <cki> 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 <vdd> net at top block level." ) << endl;
else destroyRing( _vddi );
if (_vssi == NULL) cerr << Error("Missing <vss> net at top block level." ) << endl;
else destroyRing( _vssi );
}
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 );

View File

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

View File

@ -24,12 +24,6 @@
#include "katana/KatanaEngine.h"
namespace {
} // Anonymous namespace.
namespace Katana {
using namespace std;