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; cdebug_log(145,1) << getTypeName() << "::_do_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
AutoContact* rpContact = doRp_Access( getGCell(), getRoutingPads()[0], NoFlags ); AutoContact* rpContactSource = NULL;
AutoContact* rpContactTarget = NULL;
doRp_AutoContacts( getGCell(), getRoutingPads()[0], rpContactSource, rpContactTarget, NoFlags );
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );
AutoSegment::create( rpContact, turn1, Flags::Vertical ); 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()) { if (north() or south()) {
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) ); AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(1) );

View File

@ -73,6 +73,8 @@ namespace Anabatic {
openSession(); openSession();
size_t toBeRouteds = 0; size_t toBeRouteds = 0;
Box ab = getCell()->getAbutmentBox();
ab.inflate( -1 );
for ( Net* net : getCell()->getNets() ) { for ( Net* net : getCell()->getNets() ) {
if (net == _blockageNet) continue; if (net == _blockageNet) continue;
@ -96,6 +98,9 @@ namespace Anabatic {
Horizontal* horizontal = dynamic_cast<Horizontal*>(component); Horizontal* horizontal = dynamic_cast<Horizontal*>(component);
if (horizontal) { if (horizontal) {
if ( not ab.contains(horizontal->getSourcePosition())
and not ab.contains(horizontal->getTargetPosition()) ) continue;
segments.push_back( horizontal ); segments.push_back( horizontal );
isPreRouted = true; isPreRouted = true;
if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer())) if (horizontal->getWidth() != Session::getWireWidth(horizontal->getLayer()))
@ -103,6 +108,9 @@ namespace Anabatic {
} else { } else {
Vertical* vertical = dynamic_cast<Vertical*>(component); Vertical* vertical = dynamic_cast<Vertical*>(component);
if (vertical) { if (vertical) {
if ( not ab.contains(vertical->getSourcePosition())
and not ab.contains(vertical->getTargetPosition()) ) continue;
isPreRouted = true; isPreRouted = true;
segments.push_back( vertical ); segments.push_back( vertical );
if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer())) if (vertical->getWidth() != Session::getWireWidth(vertical->getLayer()))
@ -110,6 +118,8 @@ namespace Anabatic {
} else { } else {
Contact* contact = dynamic_cast<Contact*>(component); Contact* contact = dynamic_cast<Contact*>(component);
if (contact) { if (contact) {
if (not ab.contains(contact->getCenter())) continue;
isPreRouted = true; isPreRouted = true;
contacts.push_back( contact ); contacts.push_back( contact );
if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer())) if ( (contact->getWidth () != Session::getViaWidth(contact->getLayer()))
@ -165,10 +175,10 @@ namespace Anabatic {
AutoContact::createFrom( icontact ); AutoContact::createFrom( icontact );
} }
for ( auto isegment : segments ) { for ( auto segment : segments ) {
AutoContact* source = Session::lookup( dynamic_cast<Contact*>( isegment->getSource() )); AutoContact* source = Session::lookup( dynamic_cast<Contact*>( segment->getSource() ));
AutoContact* target = Session::lookup( dynamic_cast<Contact*>( isegment->getTarget() )); AutoContact* target = Session::lookup( dynamic_cast<Contact*>( segment->getTarget() ));
AutoSegment* autoSegment = AutoSegment::create( source, target, isegment ); AutoSegment* autoSegment = AutoSegment::create( source, target, segment );
autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet ); autoSegment->setFlags( AutoSegment::SegUserDefined|AutoSegment::SegAxisSet );
} }
} }

View File

@ -39,6 +39,7 @@ namespace Anabatic {
virtual bool _do_2G_1M1 (); virtual bool _do_2G_1M1 ();
virtual bool _do_xG_1Pad (); virtual bool _do_xG_1Pad ();
virtual bool _do_1G_1PinM2 (); virtual bool _do_1G_1PinM2 ();
virtual bool _do_1G_1PinM3 ();
virtual bool _do_xG_1M1 (); virtual bool _do_xG_1M1 ();
virtual bool _do_xG_1M1_1M2 (); virtual bool _do_xG_1M1_1M2 ();
virtual bool _do_xG_xM1_xM3 (); virtual bool _do_xG_xM1_xM3 ();

View File

@ -1,6 +1,7 @@
# -*- Mode:Python; explicit-buffer-name: "plugins.conf<cmos>" -*- # -*- Mode:Python; explicit-buffer-name: "plugins.conf<cmos>" -*-
import helpers import helpers
from helpers import l, u, n
# Contains the layout (shared by all technologies). # Contains the layout (shared by all technologies).
#execfile( helpers.sysConfDir+'/common/plugins.conf' ) #execfile( helpers.sysConfDir+'/common/plugins.conf' )
@ -9,10 +10,10 @@ import helpers
# Parameters for chip plugin. # Parameters for chip plugin.
parametersTable = \ parametersTable = \
( ("chip.block.rails.count" , TypeInt , 5 ) ( ("chip.block.rails.count" , TypeInt , 5 )
, ("chip.block.rails.hWidth" , TypeInt , 12 ) , ("chip.block.rails.hWidth" , TypeInt , l(12) )
, ("chip.block.rails.vWidth" , TypeInt , 12 ) , ("chip.block.rails.vWidth" , TypeInt , l(12) )
, ("chip.block.rails.hSpacing" , TypeInt , 6 ) , ("chip.block.rails.hSpacing" , TypeInt , l(6) )
, ("chip.block.rails.vSpacing" , TypeInt , 6 ) , ("chip.block.rails.vSpacing" , TypeInt , l(6) )
, ('chip.pad.pck' , TypeString, 'pck_px') , ('chip.pad.pck' , TypeString, 'pck_px')
, ('chip.pad.pvddick' , TypeString, 'pvddick_px') , ('chip.pad.pvddick' , TypeString, 'pvddick_px')
, ('chip.pad.pvssick' , TypeString, 'pvssick_px') , ('chip.pad.pvssick' , TypeString, 'pvssick_px')

View File

@ -336,12 +336,21 @@ void DumpPins(ofstream &ccell, Cell* cell)
} }
indexesSet.insert(index); indexesSet.insert(index);
if (pin->getWidth() != pin->getHeight()) if (pin->getWidth() != pin->getHeight())
throw Warning(getString(pin->getName()) + " of " throw Warning( "CRL::ApParser(): Pin \"" + getString(pin->getName()) + "\" of \""
+ getString(net->getName()) + getString(net->getName())
+ " will be incompletely saved ... : AP format is only able to save square pins ..."); + "\", 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()) ccell << "C " << toMBKlambda(pin->getX())
<< "," << toMBKlambda(pin->getY()) << "," << toMBKlambda(pin->getY())
<< "," << toMBKlambda(pin->getWidth()) << "," << toMBKlambda(width)
<< "," << toMBKName(pinName) << "," << toMBKName(pinName)
<< "," << index << "," << index
<< ","; << ",";

View File

@ -154,7 +154,6 @@ namespace CRL {
AllianceFramework* af = AllianceFramework::get(); AllianceFramework* af = AllianceFramework::get();
pitch = af->getCellGauge()->getPitch(); pitch = af->getCellGauge()->getPitch();
size_t count = 0;
UpdateSession::open (); UpdateSession::open ();
unique_ptr<Bookshelf::Circuit> circuit ( Bookshelf::Circuit::parse( benchmark unique_ptr<Bookshelf::Circuit> circuit ( Bookshelf::Circuit::parse( benchmark
@ -173,11 +172,6 @@ namespace CRL {
for ( auto net : circuit->getNets() ) { for ( auto net : circuit->getNets() ) {
dots.dot(); dots.dot();
Net::create ( cell, net->getName() ); Net::create ( cell, net->getName() );
if (++count % 1000) {
UpdateSession::close ();
UpdateSession::open ();
}
} }
dots.finish( Dots::Reset|Dots::FirstDot ); dots.finish( Dots::Reset|Dots::FirstDot );
@ -202,11 +196,6 @@ namespace CRL {
Net* masterNet = master->getNet( netName ); Net* masterNet = master->getNet( netName );
instance->getPlug( masterNet )->setNet( cell->getNet(netName) ); instance->getPlug( masterNet )->setNet( cell->getNet(netName) );
} }
if (++count % 1000) {
UpdateSession::close ();
UpdateSession::open ();
}
} }
dots.finish( Dots::Reset|Dots::FirstDot ); dots.finish( Dots::Reset|Dots::FirstDot );

View File

@ -522,6 +522,8 @@ namespace {
Net* net = Net::create( parser->getCell(), pin->name() ); Net* net = Net::create( parser->getCell(), pin->name() );
net->setExternal( true ); net->setExternal( true );
if (pin->name()[ strlen(pin->name())-1 ] == '!') net->setGlobal( true );
if (pin->hasDirection()) { if (pin->hasDirection()) {
string lefDir = pin->direction(); string lefDir = pin->direction();
boost::to_upper( lefDir ); boost::to_upper( lefDir );

View File

@ -5,7 +5,8 @@
${CMAKE_CURRENT_SOURCE_DIR}/Alliance.py ${CMAKE_CURRENT_SOURCE_DIR}/Alliance.py
) )
set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py set ( pyPlugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/ChipPlugin.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/ClockTreePlugin.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePlugin.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePlugin.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePluginAll.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/RSavePluginAll.py
@ -15,10 +16,11 @@
${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/ClockTree.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/clocktree/ClockTree.py
) )
set ( pyPluginChip ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/__init__.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/BlockPower.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/BlockCorona.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/BlockCorona.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/PadsCorona.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/PadsCorona.py
${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/Configuration.py ${CMAKE_CURRENT_SOURCE_DIR}/plugins/chip/Chip.py
) )
install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus ) install ( FILES ${pySources} DESTINATION ${PYTHON_SITE_PACKAGES}/cumulus )

View File

@ -10,56 +10,18 @@
# | Author : Jean-Paul CHAPUT | # | Author : Jean-Paul CHAPUT |
# | E-mail : Jean-Paul.Chaput@asim.lip6.fr | # | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
# | =============================================================== | # | =============================================================== |
# | Python : "./plugins/ChipPlugin.py" | # | Python : "./plugins/ChipPlace.py" |
# +-----------------------------------------------------------------+ # +-----------------------------------------------------------------+
try: try:
import sys import sys
import traceback 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 import helpers
from helpers import ErrorMessage from helpers import ErrorMessage
from helpers import WarningMessage from helpers import WarningMessage
#import Nimbus
#import Metis
#import Mauka
import Etesian
import Katabatic
import Kite
import Unicorn
import plugins import plugins
import clocktree.ClockTree import chip.Chip
import chip.Configuration
import chip.BlockPower
import chip.BlockCorona
import chip.PadsCorona
except ImportError, e: except ImportError, e:
serror = str(e) serror = str(e)
if serror.startswith('No module named'): if serror.startswith('No module named'):
@ -79,112 +41,13 @@ except Exception, e:
sys.exit(2) 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 # Plugin hook functions, unicornHook:menus, ScritMain:call
def unicornHook ( **kw ): def unicornHook ( **kw ):
kw['beforeAction'] = 'placeAndRoute.stepByStep' kw['beforeAction'] = 'placeAndRoute.stepByStep'
plugins.kwAddMenu ( 'placeAndRoute', 'P&&R', **kw )
plugins.kwUnicornHook( 'placeAndRoute.placeChip' plugins.kwUnicornHook( 'placeAndRoute.placeChip'
, 'PLace Chip' , 'PLace Chip'
, 'Place a Complete Chip (pads && core)' , 'Place a Complete Chip (pads && core)'
@ -203,31 +66,11 @@ def ScriptMain ( **kw ):
cell, editor = plugins.kwParseMain( **kw ) cell, editor = plugins.kwParseMain( **kw )
conf = chip.Configuration.loadConfiguration( cell, editor ) conf = chip.Configuration.loadConfiguration( cell, editor )
if not conf.isValid(): return if not conf.validated: return False
padsCorona = chip.PadsCorona.Corona( conf ) placeChip = chip.Chip.PlaceRoute( conf )
if not padsCorona.validate(): return placeChip.doChipPlacement()
return placeChip.validated
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()
except ErrorMessage, e: except ErrorMessage, e:
print e; errorCode = e.code 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 import helpers
from helpers import trace from helpers import trace
from helpers import ErrorMessage from helpers import ErrorMessage
#import Mauka
import Etesian import Etesian
import Unicorn import Unicorn
import plugins import plugins
@ -56,8 +55,9 @@ except Exception, e:
# Plugin hook functions, unicornHook:menus, ScritMain:call # Plugin hook functions, unicornHook:menus, ScritMain:call
def unicornHook ( **kw ): def unicornHook ( **kw ):
kw['beforeAction'] = 'placeAndRoute.placeChip' kw['beforeAction'] = 'beta.placeAndRoute.placeChip'
plugins.kwAddMenu ( 'placeAndRoute', 'P&&R', **kw )
plugins.kwUnicornHook( 'placeAndRoute.clockTree' plugins.kwUnicornHook( 'placeAndRoute.clockTree'
, 'Place Block && Clock Tree' , 'Place Block && Clock Tree'
, 'Place a block with a buffered H-Tree for the clock' , 'Place a block with a buffered H-Tree for the clock'
@ -93,24 +93,17 @@ def ScriptMain ( **kw ):
if cell == None: if cell == None:
raise ErrorMessage( 3, 'ClockTree: No cell loaded yet.' ) raise ErrorMessage( 3, 'ClockTree: No cell loaded yet.' )
framework = CRL.AllianceFramework.get() conf = chip.Configuration.ChipConf( {}, cell, editor )
cellGauge = framework.getCellGauge()
if cell.getAbutmentBox().isEmpty(): if cell.getAbutmentBox().isEmpty():
spaceMargin = Cfg.getParamPercentage('etesian.spaceMargin').asPercentage() / 100.0 + 0.02 spaceMargin = Cfg.getParamPercentage('etesian.spaceMargin').asPercentage() / 100.0 + 0.02
aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0 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() if editor: editor.fit()
ht = clocktree.ClockTree.HTree.create( chip.Configuration.GaugeConfWrapper(chip.Configuration.GaugeConf()) ht = clocktree.ClockTree.HTree.create( conf, cell, None, cell.getAbutmentBox() )
, cell, None, cell.getAbutmentBox() )
if editor: editor.refresh() 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 = Etesian.EtesianEngine.create( cell )
etesian.place() etesian.place()
etesian.destroy() etesian.destroy()
@ -120,11 +113,6 @@ def ScriptMain ( **kw ):
ht.route() ht.route()
ht.save( cell ) 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: except ErrorMessage, e:
print e; errorCode = e.code print e; errorCode = e.code
except Exception, e: except Exception, e:

View File

@ -21,6 +21,7 @@ from Hurricane import Contact
from Hurricane import Path from Hurricane import Path
from Hurricane import Occurrence from Hurricane import Occurrence
from Hurricane import Instance from Hurricane import Instance
import Viewer
import CRL import CRL
from CRL import RoutingLayerGauge from CRL import RoutingLayerGauge
@ -47,6 +48,15 @@ def kwParseMain ( **kw ):
return cell, editor 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 ): def kwUnicornHook ( menuPath, menuName, menuTip, moduleFile, **kw ):
editor = kw['editor'] editor = kw['editor']
if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'): if moduleFile.endswith('.pyc') or moduleFile.endswith('.pyo'):

View File

@ -131,7 +131,11 @@ class HorizontalRail ( Rail ):
, self.side.hRailWidth - DbU.fromLambda(1.0) , self.side.hRailWidth - DbU.fromLambda(1.0)
) )
, contact ] , 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()) ) self.vias[ contact.getX() ][1].mergeDepth( self.side.getLayerDepth(contact.getLayer()) )
return True return True
@ -144,6 +148,7 @@ class HorizontalRail ( Rail ):
for via in self.vias.values(): for via in self.vias.values():
if via[1].getNet() != via[2].getNet(): continue if via[1].getNet() != via[2].getNet(): continue
via[1].mergeDepth( self.side.getLayerDepth(self.side.getVLayer()) )
via[1].doLayout() via[1].doLayout()
#print ' Connect:', via[2], via[1].getVia( via[2].getLayer() ) #print ' Connect:', via[2], via[1].getVia( via[2].getLayer() )
Vertical.create( 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].getX()
, via[2].getWidth() , 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.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)): for i in range(1,len(railVias)):
Horizontal.create( railVias[i-1] Horizontal.create( railVias[i-1]
@ -273,84 +281,85 @@ class VerticalRail ( Rail ):
class Side ( object ): class Side ( object ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
self._corona = corona self.corona = corona
return return
@property @property
def railsNb ( self ): return self._corona._railsNb def railsNb ( self ): return self.corona.railsNb
@property @property
def innerBb ( self ): return self._corona._innerBb def innerBb ( self ): return self.corona.innerBb
@property @property
def hRailWidth ( self ): return self._corona._hRailWidth def hRailWidth ( self ): return self.corona.hRailWidth
@property @property
def hRailSpace ( self ): return self._corona._hRailSpace def hRailSpace ( self ): return self.corona.hRailSpace
@property @property
def vRailWidth ( self ): return self._corona._vRailWidth def vRailWidth ( self ): return self.corona.vRailWidth
@property @property
def vRailSpace ( self ): return self._corona._vRailSpace def vRailSpace ( self ): return self.corona.vRailSpace
@property @property
def corners ( self ): return self._corona._corners def corners ( self ): return self.corona.corners
@property @property
def horizontalDepth ( self ): return self._corona.horizontalDepth def horizontalDepth ( self ): return self.corona.horizontalDepth
@property @property
def verticalDepth ( self ): return self._corona.verticalDepth def verticalDepth ( self ): return self.corona.verticalDepth
@property @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 getLayerDepth ( self, metal ): return self.corona.getLayerDepth(metal)
def getRail ( self, i ): return self._rails[i] def getRail ( self, i ): return self.rails[i]
def getRailNet ( self, i ): return self._corona.getRailNet(i) def getRailNet ( self, i ): return self.corona.getRailNet(i)
def getHLayer ( self ): return self._corona.getHLayer() def getHLayer ( self ): return self.corona.getHLayer()
def getVLayer ( self ): return self._corona.getVLayer() def getVLayer ( self ): return self.corona.getVLayer()
def getRailAxis ( self, i ): def getRailAxis ( self, i ):
raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' ) raise ErrorMessage( 1, 'Side.getRailAxis(): Must never be called on base class.' )
def getInnerRail ( self, i ): def getInnerRail ( self, i ):
if i >= len(self._rails): if i >= len(self.rails):
raise ErrorMessage( 1, 'Side.getInnerRail(): no rail %d (only: %d).' % (i,len(self._rails)) ) raise ErrorMessage( 1, 'Side.getInnerRail(): no rail %d (only: %d).' % (i,len(self.rails)) )
return self._rails[i] return self.rails[i]
def getOuterRail ( self, i ): def getOuterRail ( self, i ):
if i >= len(self._rails): if i >= len(self.rails):
raise ErrorMessage( 1, 'Side.getOuterRail(): no rail %d (only: %d).' % (i,len(self._rails)) ) raise ErrorMessage( 1, 'Side.getOuterRail(): no rail %d (only: %d).' % (i,len(self.rails)) )
return self._rails[-(i+1)] return self.rails[-(i+1)]
def connect ( self, blockSide ): def connect ( self, blockSide ):
for terminal in blockSide.terminals: for terminal in blockSide.terminals:
for rail in self._rails: for rail in self.rails:
rail.connect( terminal[1] ) rail.connect( terminal[1] )
return return
def connectPads ( self, padSide ): 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)) #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 ) trace( 550, 'halfRails:%i' % halfRails )
for terminal in padSide._powerContacts: for contact in padSide.pins:
trace( 550, ',+', '\tConnect pad terminal %s\n' % terminal ) if not contact.getNet().isSupply() and not contact.getNet().isClock(): continue
trace( 550, ',+', '\tConnect pad contact %s\n' % contact )
for i in range(halfRails): for i in range(halfRails):
trace( 550, '\tConnect to [-%i] @%d\n' % (i+1, DbU.toLambda(self.getOuterRail(i+1).axis)) ) 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, '-' ) trace( 550, '-' )
return return
def doLayout ( self ): def doLayout ( self ):
for rail in self._rails: rail.doLayout() for rail in self.rails: rail.doLayout()
return return
class HorizontalSide ( Side ): class HorizontalSide ( Side ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
#print 'HorizontalSide.__init__()'
Side.__init__( self, corona ) Side.__init__( self, corona )
self._rails = [] self.rails = []
for i in range(self.railsNb): 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)) #print ' Rail [%i] @%d' % (i,DbU.toLambda(self._rails[-1].axis))
return return
@ -388,20 +397,20 @@ class VerticalSide ( Side ):
def __init__ ( self, corona ): def __init__ ( self, corona ):
Side.__init__( self, corona ) Side.__init__( self, corona )
self._rails = [] self.rails = []
for i in range(self.railsNb): 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 return
def addBlockages ( self, sideXMin, sideXMax ): def addBlockages ( self, sideXMin, sideXMax ):
spans = IntervalSet() spans = IntervalSet()
for rail in self._rails: for rail in self.rails:
for via in rail.vias.values(): for via in rail.vias.values():
if via[1].getNet() != via[2].getNet(): continue if via[1].getNet() != via[2].getNet(): continue
spans.merge( via[1]._y - via[1]._height/2, via[1]._y + via[1]._height/2 ) 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 for depth in range(self.getInnerRail(0).vias.values()[0][1].bottomDepth
,self.getInnerRail(0).vias.values()[0][1].topDepth ): ,self.getInnerRail(0).vias.values()[0][1].topDepth ):
blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer() blockageLayer = routingGauge.getRoutingLayer(depth).getBlockageLayer()
@ -461,49 +470,44 @@ class EastSide ( VerticalSide ):
class Corona ( object ): class Corona ( object ):
def __init__ ( self, block ): def __init__ ( self, block ):
#if not isinstance(block,plugins.chip.BlockPower.Block): self.block = block
# raise ErrorMessage( 1, 'Attempt to create a Corona on a non-Block object.' ) 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.innerBb = self.block.bb
self._hRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.hWidth' ).asInt() ) self.block.path.getTransformation().applyOn( self.innerBb )
self._vRailWidth = DbU.fromLambda( Cfg.getParamInt('chip.block.rails.vWidth' ).asInt() ) self.innerBb.inflate( self.hRailSpace/2, self.vRailSpace/2 )
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 if not self.block.conf.useClockTree: self.railsNb -= 1
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 self.southSide = SouthSide( self )
self.northSide = NorthSide( self )
self._southSide = SouthSide( self ) self.westSide = WestSide ( self )
self._northSide = NorthSide( self ) self.eastSide = EastSide ( self )
self._westSide = WestSide ( self )
self._eastSide = EastSide ( self )
return return
@property @property
def useClockTree ( self ): return self._block.useClockTree def routingGauge ( self ): return self.block.conf.gaugeConf.routingGauge
@property @property
def routingGauge ( self ): return self._block.routingGauge def topLayerDepth ( self ): return self.block.conf.gaugeConf.topLayerDepth
@property @property
def topLayerDepth ( self ): return self._block.topLayerDepth def horizontalDepth ( self ): return self.block.conf.gaugeConf.horizontalDepth
@property @property
def horizontalDepth ( self ): return self._block.horizontalDepth def verticalDepth ( self ): return self.block.conf.gaugeConf.verticalDepth
@property @property
def verticalDepth ( self ): return self._block.verticalDepth def blockageNet ( self ): return self.block.conf.blockageNet
@property
def blockageNet ( self ): return self._block.blockageNet
def getLayerDepth ( self, metal ): def getLayerDepth ( self, metal ):
return self.routingGauge.getLayerDepth( metal ) return self.block.conf.gaugeConf.routingGauge.getLayerDepth( metal )
def getRailNet ( self, i ): def getRailNet ( self, i ):
if self.useClockTree and i == self._railsNb-1: return self._block.cko if self.block.conf.useClockTree and i == self.railsNb-1: return self.block.conf.coronaCk
if i % 2: return self._block.vssi if i % 2: return self.block.conf.coronaVss
return self._block.vddi return self.block.conf.coronaVdd
def getHLayer ( self ): def getHLayer ( self ):
return self.routingGauge.getLayerGauge( self.horizontalDepth ).getLayer() return self.routingGauge.getLayerGauge( self.horizontalDepth ).getLayer()
@ -512,23 +516,23 @@ class Corona ( object ):
return self.routingGauge.getLayerGauge( self.verticalDepth ).getLayer() return self.routingGauge.getLayerGauge( self.verticalDepth ).getLayer()
def connectBlock ( self ): def connectBlock ( self ):
for plane in self._block.planes.values(): for plane in self.block.planes.values():
for side in plane.sides.values(): for side in plane.sides.values():
self._southSide.connect( side[chip.South] ) self.southSide.connect( side[chip.South] )
self._northSide.connect( side[chip.North] ) self.northSide.connect( side[chip.North] )
self._westSide .connect( side[chip.West ] ) self.westSide .connect( side[chip.West ] )
self._eastSide .connect( side[chip.East ] ) self.eastSide .connect( side[chip.East ] )
return return
def connectPads ( self, padsCorona ): def connectPads ( self, padsCorona ):
self._southSide.connectPads( padsCorona.southSide ) self.southSide.connectPads( padsCorona.southSide )
self._northSide.connectPads( padsCorona.northSide ) self.northSide.connectPads( padsCorona.northSide )
self._eastSide.connectPads( padsCorona.eastSide ) self.eastSide .connectPads( padsCorona.eastSide )
self._westSide.connectPads( padsCorona.westSide ) self.westSide .connectPads( padsCorona.westSide )
return return
def doLayout ( self ): def doLayout ( self ):
self._corners = { chip.SouthWest : [] self.corners = { chip.SouthWest : []
, chip.SouthEast : [] , chip.SouthEast : []
, chip.NorthWest : [] , chip.NorthWest : []
, chip.NorthEast : [] , chip.NorthEast : []
@ -539,49 +543,49 @@ class Corona ( object ):
contactDepth = self.verticalDepth contactDepth = self.verticalDepth
UpdateSession.open() UpdateSession.open()
for i in range(self._railsNb): for i in range(self.railsNb):
xBL = self._westSide .getRail(i).axis xBL = self.westSide .getRail(i).axis
yBL = self._southSide.getRail(i).axis yBL = self.southSide.getRail(i).axis
xTR = self._eastSide .getRail(i).axis xTR = self.eastSide .getRail(i).axis
yTR = self._northSide.getRail(i).axis yTR = self.northSide.getRail(i).axis
net = self.getRailNet( i ) net = self.getRailNet( i )
self.routingGauge.getContactLayer(contactDepth) self.routingGauge.getContactLayer(contactDepth)
self._corners[chip.SouthWest].append( self.corners[chip.SouthWest].append(
Contact.create( net Contact.create( net
, self.routingGauge.getContactLayer(contactDepth) , self.routingGauge.getContactLayer(contactDepth)
, xBL, yBL , xBL, yBL
, self._hRailWidth , self.hRailWidth
, self._vRailWidth , self.vRailWidth
) ) ) )
self._corners[chip.NorthWest].append( self.corners[chip.NorthWest].append(
Contact.create( net Contact.create( net
, self.routingGauge.getContactLayer(contactDepth) , self.routingGauge.getContactLayer(contactDepth)
, xBL, yTR , xBL, yTR
, self._hRailWidth , self.hRailWidth
, self._vRailWidth , self.vRailWidth
) ) ) )
self._corners[chip.SouthEast].append( self.corners[chip.SouthEast].append(
Contact.create( net Contact.create( net
, self.routingGauge.getContactLayer(contactDepth) , self.routingGauge.getContactLayer(contactDepth)
, xTR, yBL , xTR, yBL
, self._hRailWidth , self.hRailWidth
, self._vRailWidth , self.vRailWidth
) ) ) )
self._corners[chip.NorthEast].append( self.corners[chip.NorthEast].append(
Contact.create( net Contact.create( net
, self.routingGauge.getContactLayer(contactDepth) , self.routingGauge.getContactLayer(contactDepth)
, xTR, yTR , xTR, yTR
, self._hRailWidth , self.hRailWidth
, self._vRailWidth , self.vRailWidth
) ) ) )
self._southSide.doLayout() self.southSide.doLayout()
self._northSide.doLayout() self.northSide.doLayout()
self._westSide .doLayout() self.westSide .doLayout()
self._eastSide .doLayout() self.eastSide .doLayout()
self._westSide.addBlockages() self.westSide.addBlockages()
self._eastSide.addBlockages() self.eastSide.addBlockages()
UpdateSession.close() UpdateSession.close()
return return

View File

@ -125,11 +125,11 @@ class Plane ( object ):
def addTerminal ( self, net, direction, bb ): def addTerminal ( self, net, direction, bb ):
if not self.sides.has_key(net): if not self.sides.has_key(net):
self.sides[ net ] = [ Side(self.block,chip.North,net,self.metal) self.sides[ net ] = { chip.North : Side(self.block,chip.North,net,self.metal)
, Side(self.block,chip.South,net,self.metal) , chip.South : Side(self.block,chip.South,net,self.metal)
, Side(self.block,chip.East ,net,self.metal) , chip.East : Side(self.block,chip.East ,net,self.metal)
, Side(self.block,chip.West ,net,self.metal) , chip.West : Side(self.block,chip.West ,net,self.metal)
] }
sides = self.sides[ net ] sides = self.sides[ net ]
if direction == Plane.Horizontal: if direction == Plane.Horizontal:
@ -147,7 +147,7 @@ class Plane ( object ):
def doLayout ( self ): def doLayout ( self ):
for sidesOfNet in self.sides.values(): for sidesOfNet in self.sides.values():
for side in sidesOfNet: for side in sidesOfNet.values():
side.doLayout() side.doLayout()
return return
@ -166,8 +166,8 @@ class GoCb ( object ):
if not direction: return if not direction: return
rootNet = None rootNet = None
if go.getNet().getType() == Net.Type.POWER: rootNet = self.block.vddi if go.getNet().getType() == Net.Type.POWER: rootNet = self.block.conf.coronaVdd
if go.getNet().getType() == Net.Type.GROUND: rootNet = self.block.vssi if go.getNet().getType() == Net.Type.GROUND: rootNet = self.block.conf.coronaVss
if not rootNet: return if not rootNet: return
if self.block.activePlane: if self.block.activePlane:
@ -179,37 +179,35 @@ class GoCb ( object ):
return return
class Block ( chip.Configuration.ChipConfWrapper ): class Block ( object ):
def __init__ ( self, conf ): def __init__ ( self, conf ):
chip.Configuration.ChipConfWrapper.__init__( self, conf.gaugeConf, conf.chipConf ) self.conf = conf
self.path = Path( self.cores[0] ) self.path = Path( self.conf.icore )
self.block = self.path.getTailInstance().getMasterCell() self.block = self.path.getTailInstance().getMasterCell()
self.bb = self.block.getAbutmentBox() self.bb = self.block.getAbutmentBox()
self.planes = { } self.planes = { }
self.activePlane = None self.activePlane = None
routingGauge = CRL.AllianceFramework.get().getRoutingGauge() for layerGauge in self.conf.gaugeConf.routingGauge.getLayerGauges():
for layerGauge in routingGauge.getLayerGauges():
self.planes[ layerGauge.getLayer().getName() ] = Plane( self, layerGauge.getLayer() ) self.planes[ layerGauge.getLayer().getName() ] = Plane( self, layerGauge.getLayer() )
return return
def connectPower ( self ): def connectPower ( self ):
if not self.vddi or not self.vssi: if not self.conf.coronaVdd or not self.conf.coronaVss:
print ErrorMessage( 1, 'Cannot build block power terminals as vddi and/or vss are not known.' ) print ErrorMessage( 1, 'Cannot build block power terminals as core vdd and/or vss are not known.' )
return return
goCb = GoCb( self ) goCb = GoCb( self )
query = Query() query = Query()
query.setGoCallback( goCb ) query.setGoCallback( goCb )
query.setCell( self.block ) query.setCell( self.block )
query.setArea( self.bb ) query.setArea( self.block.getAbutmentBox() )
query.setFilter( Query.DoComponents|Query.DoTerminalCells ) query.setFilter( Query.DoComponents|Query.DoTerminalCells )
routingGauge = CRL.AllianceFramework.get().getRoutingGauge() for layerGauge in self.conf.gaugeConf.routingGauge.getLayerGauges():
for layerGauge in routingGauge.getLayerGauges():
self.activePlane = self.planes[ layerGauge.getLayer().getName() ] self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
query.setBasicLayer( layerGauge.getLayer().getBasicLayer() ) query.setBasicLayer( layerGauge.getLayer().getBasicLayer() )
query.doQuery() query.doQuery()
@ -218,17 +216,17 @@ class Block ( chip.Configuration.ChipConfWrapper ):
def connectClock ( self ): def connectClock ( self ):
if not self.useClockTree: if not self.conf.useClockTree:
print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." ) print WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." )
return return
if not self.cko: if not self.conf.coronaCk:
print ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' ) print ErrorMessage( 1, 'Cannot build clock terminal as ck is not known.' )
return return
blockCk = None blockCk = None
for plug in self.path.getTailInstance().getPlugs(): for plug in self.path.getTailInstance().getPlugs():
if plug.getNet() == self.cko: if plug.getNet() == self.conf.coronaCk:
blockCk = plug.getMasterNet() blockCk = plug.getMasterNet()
if not blockCk: if not blockCk:
@ -260,24 +258,24 @@ class Block ( chip.Configuration.ChipConfWrapper ):
return return
UpdateSession.open() 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() blockAb = self.block.getAbutmentBox()
self.path.getTransformation().applyOn( blockAb ) self.path.getTransformation().applyOn( blockAb )
layerGauge = self.routingGauge.getLayerGauge(self.verticalDepth) layerGauge = self.conf.routingGauge.getLayerGauge(self.conf.verticalDepth)
contact = Contact.create( self.cko contact = Contact.create( self.conf.coronaCk
, self.routingGauge.getRoutingLayer(self.verticalDepth) , self.conf.routingGauge.getRoutingLayer(self.conf.verticalDepth)
, bufferRp.getX() , bufferRp.getX()
, blockAb.getYMax() , blockAb.getYMax()
, layerGauge.getViaWidth() , layerGauge.getViaWidth()
, 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() ] self.activePlane = self.planes[ layerGauge.getLayer().getName() ]
bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() ) bb = segment.getBoundingBox( self.activePlane.metal.getBasicLayer() )
self.path.getTransformation().getInvert().applyOn( bb ) 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() UpdateSession.close()

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. # Common constants used through all <chip> modules.
# For Corona's sides. # For Corona's sides.
North = 0000 North = 0x0001
South = 0001 South = 0x0002
East = 0002 East = 0x0004
West = 0003 West = 0x0008
# For Corona's corners. # For Corona's corners.
SouthWest = 0000 SouthWest = South|West
SouthEast = 0001 SouthEast = South|East
NorthWest = 0002 NorthWest = North|West
NorthEast = 0003 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 import helpers
from helpers import trace from helpers import trace
from helpers import ErrorMessage from helpers import ErrorMessage
#import Nimbus
#import Metis
#import Mauka
import Katabatic
import Kite
import Unicorn import Unicorn
import plugins import plugins
from clocktree.RSMT import RSMT from clocktree.RSMT import RSMT
from chip.Configuration import GaugeConf
from chip.Configuration import getPlugByNet from chip.Configuration import getPlugByNet
from chip.Configuration import getPlugByName from chip.Configuration import getPlugByName
from chip.Configuration import getRpBb from chip.Configuration import getRpBb
from chip.Configuration import destroyNetComponents from chip.Configuration import destroyNetComponents
from chip.Configuration import GaugeConf
from chip.Configuration import GaugeConfWrapper
except ImportError, e: except ImportError, e:
serror = str(e) serror = str(e)
if serror.startswith('No module named'): if serror.startswith('No module named'):
@ -75,7 +69,7 @@ except Exception, e:
sys.exit(2) sys.exit(2)
class HTree ( GaugeConfWrapper ): class HTree ( object ):
@staticmethod @staticmethod
def create ( conf, cell, clockNet, clockBox ): def create ( conf, cell, clockNet, clockBox ):
@ -99,7 +93,7 @@ class HTree ( GaugeConfWrapper ):
return ht return ht
def __init__ ( self, conf, cell, clockNet, area ): def __init__ ( self, conf, cell, clockNet, area ):
GaugeConfWrapper.__init__( self, conf.gaugeConf ) self.conf = conf
self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt() ) self.minSide = DbU.fromLambda( Cfg.getParamInt('clockTree.minimumSide').asInt() )
if self.minSide < DbU.fromLambda(100.0): if self.minSide < DbU.fromLambda(100.0):
@ -113,7 +107,6 @@ class HTree ( GaugeConfWrapper ):
self.childs = [] self.childs = []
self._getBufferIo() self._getBufferIo()
self.tieCell = self.framework.getCell( 'rowend_x0', CRL.Catalog.State.Views ) 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.topBuffer = Instance.create( self.cell, 'ck_htree', self.bufferCell )
self.cloneds = [ self.cell ] self.cloneds = [ self.cell ]
self.usedVTracks = [] self.usedVTracks = []
@ -160,8 +153,8 @@ class HTree ( GaugeConfWrapper ):
self._feedCount += 1 self._feedCount += 1
return self._feedCount return self._feedCount
def toXCellGrid ( self, x ): return x - (x % self.cellGauge.getSliceStep ()) def toXCellGrid ( self, x ): return x - (x % self.conf.cellGauge.getSliceStep ())
def toYCellGrid ( self, y ): return y - (y % self.cellGauge.getSliceHeight()) def toYCellGrid ( self, y ): return y - (y % self.conf.cellGauge.getSliceHeight())
def rpDistance ( self, rp1, rp2 ): def rpDistance ( self, rp1, rp2 ):
dx = abs( rp1.getX() - rp2.getX() ) dx = abs( rp1.getX() - rp2.getX() )
@ -173,9 +166,9 @@ class HTree ( GaugeConfWrapper ):
yslice = self.toYCellGrid(y) yslice = self.toYCellGrid(y)
transformation = Transformation.Orientation.ID 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 transformation = Transformation.Orientation.MY
yslice += self.cellGauge.getSliceHeight() yslice += self.conf.cellGauge.getSliceHeight()
instance.setTransformation ( Transformation(xslice, yslice, transformation) ) instance.setTransformation ( Transformation(xslice, yslice, transformation) )
instance.setPlacementStatus( Instance.PlacementStatus.FIXED ) instance.setPlacementStatus( Instance.PlacementStatus.FIXED )
@ -193,7 +186,7 @@ class HTree ( GaugeConfWrapper ):
, 'htree_feed_%i' % self.feedCounter() , 'htree_feed_%i' % self.feedCounter()
, self.tieCell , self.tieCell
, Transformation(x,transformation.getTy(),transformation.getOrientation()) , Transformation(x,transformation.getTy(),transformation.getOrientation())
#, Instance.PlacementStatus.PLACED , Instance.PlacementStatus.PLACED
) )
x += tieWidth x += tieWidth
return return
@ -267,16 +260,16 @@ class HTree ( GaugeConfWrapper ):
if not node.component: if not node.component:
x = node.realX x = node.realX
if node.realX in self.usedVTracks: 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. # This is a Steiner point.
node.component = self.createContact( net node.component = self.conf.createContact( net
, x , x
, node.y + self.cellGauge.getSliceHeight()/2 - self.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch() , node.y + self.conf.cellGauge.getSliceHeight()/2 - self.conf.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch()
, GaugeConf.DeepDepth ) , GaugeConf.DeepDepth )
trace( 550, '\tCreate (Steiner) node.component: @Y%d (y:%d - %d) %s\n' \ trace( 550, '\tCreate (Steiner) node.component: @Y%d (y:%d - %d) %s\n' \
% (DbU.toLambda(node.realY) % (DbU.toLambda(node.realY)
,DbU.toLambda(node.y) ,DbU.toLambda(node.y)
,DbU.toLambda(self.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch()) ,DbU.toLambda(self.conf.routingGauge.getLayerGauge(self.horizontalDeepDepth).getPitch())
,node.component) ) ,node.component) )
else: else:
# This a terminal (graph) point # This a terminal (graph) point
@ -289,7 +282,7 @@ class HTree ( GaugeConfWrapper ):
flags |= GaugeConf.OffsetTop1 flags |= GaugeConf.OffsetTop1
if node.realX in self.usedVTracks: if node.realX in self.usedVTracks:
flags |= GaugeConf.OffsetRight1 flags |= GaugeConf.OffsetRight1
node.component = self.rpAccess( node.component, flags ) node.component = self.conf.rpAccess( node.component, flags )
for edge in mst.edges: for edge in mst.edges:
sourceContact = edge.source.component sourceContact = edge.source.component
@ -300,12 +293,12 @@ class HTree ( GaugeConfWrapper ):
elif edge.isVertical(): elif edge.isVertical():
self.createVertical ( sourceContact, targetContact, sourceContact.getX(), GaugeConf.DeepDepth ) self.createVertical ( sourceContact, targetContact, sourceContact.getX(), GaugeConf.DeepDepth )
else: else:
turn = self.createContact( edge.source.component.getNet() turn = self.conf.createContact( edge.source.component.getNet()
, sourceContact.getX() , sourceContact.getX()
, targetContact.getY() , targetContact.getY()
, GaugeConf.DeepDepth ) , GaugeConf.DeepDepth )
self.createVertical ( sourceContact, turn, sourceContact.getX(), GaugeConf.DeepDepth ) self.conf.createVertical ( sourceContact, turn, sourceContact.getX(), GaugeConf.DeepDepth )
self.createHorizontal( turn, targetContact, targetContact.getY(), GaugeConf.DeepDepth ) self.conf.createHorizontal( turn, targetContact, targetContact.getY(), GaugeConf.DeepDepth )
return return
def _connectLeafs ( self, leafBuffer, leafs ): def _connectLeafs ( self, leafBuffer, leafs ):
@ -512,8 +505,8 @@ class HTreeNode ( object ):
self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight ) self.topTree.placeInstance( self.trBuffer, x+halfWidth, y+halfHeight )
self.topTree.usedVTracks += \ self.topTree.usedVTracks += \
[ self.topTree.rpAccessByPlugName( self.blBuffer, self.topTree.bufferIn, self.ckNet ).getX() [ self.topTree.conf.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.brBuffer, self.topTree.bufferIn, self.ckNet ).getX() ]
for child in self.childs: child.place() for child in self.childs: child.place()
return return
@ -521,42 +514,42 @@ class HTreeNode ( object ):
def route ( self ): def route ( self ):
trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() ) trace( 550, '\tHTreeNode.route() %s\n' % self.sourceBuffer.getName() )
leftSourceContact = self.topTree.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 ) leftSourceContact = self.topTree.conf.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 ) rightSourceContact = self.topTree.conf.rpAccessByPlugName( self.sourceBuffer, self.topTree.bufferOut, self.ckNet , GaugeConf.HAccess|GaugeConf.OffsetBottom1 )
blContact = self.topTree.rpAccessByPlugName( self.blBuffer , self.topTree.bufferIn , self.ckNet ) blContact = self.topTree.conf.rpAccessByPlugName( self.blBuffer , self.topTree.bufferIn , self.ckNet )
brContact = self.topTree.rpAccessByPlugName( self.brBuffer , self.topTree.bufferIn , self.ckNet ) brContact = self.topTree.conf.rpAccessByPlugName( self.brBuffer , self.topTree.bufferIn , self.ckNet )
tlContact = self.topTree.rpAccessByPlugName( self.tlBuffer , self.topTree.bufferIn , self.ckNet ) tlContact = self.topTree.conf.rpAccessByPlugName( self.tlBuffer , self.topTree.bufferIn , self.ckNet )
trContact = self.topTree.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet ) trContact = self.topTree.conf.rpAccessByPlugName( self.trBuffer , self.topTree.bufferIn , self.ckNet )
leftContact = self.topTree.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() ) leftContact = self.topTree.conf.createContact( self.ckNet, blContact.getX(), leftSourceContact.getY() )
rightContact = self.topTree.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() ) rightContact = self.topTree.conf.createContact( self.ckNet, brContact.getX(), rightSourceContact.getY() )
leftSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftSourceContact.getX(), 0 ) leftSourceX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, leftSourceContact.getX(), 0 )
leftSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, leftSourceContact.getY(), 0 ) leftSourceY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, leftSourceContact.getY(), 0 )
rightSourceX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightSourceContact.getX(), 0 ) rightSourceX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, rightSourceContact.getX(), 0 )
rightSourceY = self.topTree.getNearestHorizontalTrack( self.topTree.area, rightSourceContact.getY(), 0 ) rightSourceY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, rightSourceContact.getY(), 0 )
leftX = self.topTree.getNearestVerticalTrack ( self.topTree.area, leftContact.getX(), 0 ) leftX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, leftContact.getX(), 0 )
rightX = self.topTree.getNearestVerticalTrack ( self.topTree.area, rightContact.getX(), 0 ) rightX = self.topTree.conf.getNearestVerticalTrack ( self.topTree.area, rightContact.getX(), 0 )
tlY = self.topTree.getNearestHorizontalTrack( self.topTree.area, tlContact.getY(), 0 ) tlY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, tlContact.getY(), 0 )
blY = self.topTree.getNearestHorizontalTrack( self.topTree.area, blContact.getY(), 0 ) blY = self.topTree.conf.getNearestHorizontalTrack( self.topTree.area, blContact.getY(), 0 )
self.topTree.setStackPosition( leftSourceContact, leftSourceX, leftSourceY ) self.topTree.conf.setStackPosition( leftSourceContact, leftSourceX, leftSourceY )
self.topTree.setStackPosition( rightSourceContact, rightSourceX, rightSourceY ) self.topTree.conf.setStackPosition( rightSourceContact, rightSourceX, rightSourceY )
self.topTree.setStackPosition( tlContact, leftX, tlY ) self.topTree.conf.setStackPosition( tlContact, leftX, tlY )
self.topTree.setStackPosition( blContact, leftX, blY ) self.topTree.conf.setStackPosition( blContact, leftX, blY )
self.topTree.setStackPosition( trContact, rightX, tlY ) self.topTree.conf.setStackPosition( trContact, rightX, tlY )
self.topTree.setStackPosition( brContact, rightX, blY ) self.topTree.conf.setStackPosition( brContact, rightX, blY )
leftContact .setX( leftX ) leftContact .setX( leftX )
leftContact .setY( leftSourceY ) leftContact .setY( leftSourceY )
rightContact.setX( rightX ) rightContact.setX( rightX )
rightContact.setY( rightSourceY ) rightContact.setY( rightSourceY )
self.topTree.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 ) self.topTree.conf.createHorizontal( leftContact , leftSourceContact, leftSourceY , 0 )
self.topTree.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 ) self.topTree.conf.createHorizontal( rightSourceContact, rightContact , rightSourceY, 0 )
self.topTree.createVertical ( leftContact , blContact , leftX , 0 ) self.topTree.conf.createVertical ( leftContact , blContact , leftX , 0 )
self.topTree.createVertical ( tlContact , leftContact , leftX , 0 ) self.topTree.conf.createVertical ( tlContact , leftContact , leftX , 0 )
self.topTree.createVertical ( rightContact , brContact , rightX , 0 ) self.topTree.conf.createVertical ( rightContact , brContact , rightX , 0 )
self.topTree.createVertical ( trContact , rightContact , rightX , 0 ) self.topTree.conf.createVertical ( trContact , rightContact , rightX , 0 )
for child in self.childs: child.route() for child in self.childs: child.route()
return return

View File

@ -325,6 +325,7 @@ namespace Katana {
autoSegment->getConstraints( constraints ); autoSegment->getConstraints( constraints );
uside.intersection( constraints ); uside.intersection( constraints );
cdebug_log(159,0) << "* Constraints " << constraints << endl;
cdebug_log(159,0) << "* Nearest " << track << endl; cdebug_log(159,0) << "* Nearest " << track << endl;
if (not track) if (not track)

View File

@ -107,65 +107,41 @@ namespace {
bool isCoreClockNetRouted ( const Net* ) const; bool isCoreClockNetRouted ( const Net* ) const;
inline Cell* getTopCell () const; inline Cell* getTopCell () const;
Net* getRootNet ( const Net*, Path ) const; Net* getRootNet ( const Net*, Path ) const;
inline Net* getVdde () const; inline Net* getVdd () const;
inline Net* getVddi () const; inline Net* getVss () const;
inline Net* getVsse () const;
inline Net* getVssi () const;
inline Net* getCk () const; inline Net* getCk () const;
inline Net* getCki () const;
inline Net* getCko () const;
inline Net* getBlockage () const; inline Net* getBlockage () const;
inline void setBlockage ( Net* ); inline void setBlockage ( Net* );
private: private:
bool guessGlobalNet ( const Name&, Net* ); bool guessGlobalNet ( const Name&, Net* );
private: private:
uint32_t _flags; uint32_t _flags;
Name _vddePadNetName; Name _vddCoreName;
Name _vddiPadNetName; Name _vssCoreName;
Name _vssePadNetName; Name _ckCoreName;
Name _vssiPadNetName; Net* _vdd;
Name _ckPadNetName; Net* _vss;
Name _ckiPadNetName; Net* _ck;
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).
Net* _blockage; Net* _blockage;
Cell* _topCell; Cell* _topCell;
}; };
inline Cell* GlobalNetTable::getTopCell () const { return _topCell; } inline Cell* GlobalNetTable::getTopCell () const { return _topCell; }
inline Net* GlobalNetTable::getVdde () const { return _vdde; } inline Net* GlobalNetTable::getVdd () const { return _vdd; }
inline Net* GlobalNetTable::getVddi () const { return _vddi; } inline Net* GlobalNetTable::getVss () const { return _vss; }
inline Net* GlobalNetTable::getVsse () const { return _vsse; }
inline Net* GlobalNetTable::getVssi () const { return _vssi; }
inline Net* GlobalNetTable::getCk () const { return _ck; } 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 Net* GlobalNetTable::getBlockage () const { return _blockage; }
inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; } inline void GlobalNetTable::setBlockage ( Net* net ) { _blockage=net; }
GlobalNetTable::GlobalNetTable ( KatanaEngine* katana ) GlobalNetTable::GlobalNetTable ( KatanaEngine* katana )
: _flags (0) : _flags (0)
, _vddePadNetName("vdde") , _vddCoreName()
, _vddiPadNetName("vddi") , _vssCoreName()
, _vssePadNetName("vsse") , _ckCoreName ()
, _vssiPadNetName("vssi") , _vdd (NULL)
, _ckPadNetName ("pad" ) , _vss (NULL)
, _ckiPadNetName ("ck" )
, _ckoPadNetName ("cko" )
, _vdde (NULL)
, _vddi (NULL)
, _vsse (NULL)
, _vssi (NULL)
, _ck (NULL) , _ck (NULL)
, _cki (NULL)
, _cko (NULL)
, _blockage (NULL) , _blockage (NULL)
, _topCell (katana->getCell()) , _topCell (katana->getCell())
{ {
@ -173,95 +149,16 @@ namespace {
cmess1 << " o Looking for powers/grounds & clocks." << endl; cmess1 << " o Looking for powers/grounds & clocks." << endl;
AllianceFramework* af = AllianceFramework::get();
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;
}
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 );
}
}
padName = getString( instance->getMasterCell()->getName() );
if (padName.substr(0,4) == "pck_") {
cmess1 << " o Reference clock pad: " << instance->getName()
<< "(model:" << instance->getMasterCell()->getName() << ")." << endl;
// 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 (masterNet->getName() == _ckPadNetName) {
cmess1 << " - Using <" << net->getName() << "> as external chip clock net." << endl;
_ck = net;
}
}
}
}
}
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() ) { for( Net* net : _topCell->getNets() ) {
Net::Type netType = net->getType(); Net::Type netType = net->getType();
if (netType == Net::Type::CLOCK) { if (netType == Net::Type::CLOCK) {
if (not net->isExternal()) continue; if (not net->isExternal()) continue;
if (_ckoPadNetName.isEmpty()) { if (_ckCoreName.isEmpty()) {
cmess1 << " - Using <" << net->getName() << "> as internal (core) clock net." << endl; cmess1 << " - Using <" << net->getName() << "> as internal (core) clock net." << endl;
_ckoPadNetName = net->getName(); _ckCoreName = net->getName();
_cko = net; _ck = net;
if (NetRoutingExtension::isMixedPreRoute(net)) { if (NetRoutingExtension::isMixedPreRoute(net)) {
cmess1 << " (core clock net is already routed)" << endl; cmess1 << " (core clock net is already routed)" << endl;
_flags |= ClockIsRouted; _flags |= ClockIsRouted;
@ -272,7 +169,7 @@ namespace {
cerr << Error("Second clock net <%s> net at top block level will be ignored.\n" cerr << Error("Second clock net <%s> net at top block level will be ignored.\n"
" (will consider only <%s>)" " (will consider only <%s>)"
, getString(net->getName()).c_str() , getString(net->getName()).c_str()
, getString(_cko->getName()).c_str() , getString(_ck->getName()).c_str()
) << endl; ) << endl;
} }
} }
@ -280,79 +177,60 @@ namespace {
if (NetRoutingExtension::isManualGlobalRoute(net)) continue; if (NetRoutingExtension::isManualGlobalRoute(net)) continue;
if (netType == Net::Type::POWER) { if (netType == Net::Type::POWER) {
if (_vddiPadNetName.isEmpty()) { if (_vddCoreName.isEmpty()) {
_vddiPadNetName = net->getName(); _vddCoreName = net->getName();
_vddi = net; _vdd = net;
} else { } else {
cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n" cerr << Error("Second power supply net <%s> net at top block level will be ignored.\n"
" (will consider only <%s>)" " (will consider only <%s>)"
, getString(net ->getName()).c_str() , getString(net ->getName()).c_str()
, getString(_vddi->getName()).c_str() , getString(_vdd->getName()).c_str()
) << endl; ) << endl;
} }
} }
if (netType == Net::Type::GROUND) { if (netType == Net::Type::GROUND) {
if (_vssiPadNetName.isEmpty()) { if (_vssCoreName.isEmpty()) {
_vssiPadNetName = net->getName(); _vssCoreName = net->getName();
_vssi = net; _vss = net;
} else { } else {
cerr << Error("Second power ground net <%s> net at top block level will be ignored.\n" cerr << Error("Second power ground net <%s> net at top block level will be ignored.\n"
" (will consider only <%s>)" " (will consider only <%s>)"
, getString(net ->getName()).c_str() , getString(net ->getName()).c_str()
, getString(_vssi->getName()).c_str() , getString(_vss->getName()).c_str()
) << endl; ) << endl;
} }
} }
} }
if (_vddi == NULL) cerr << Error("Missing <vdd> net at top block level." ) << endl; if (_vdd == NULL) cerr << Error("Missing POWER net at top block level." ) << endl;
else destroyRing( _vddi ); else destroyRing( _vdd );
if (_vssi == NULL) cerr << Error("Missing <vss> net at top block level." ) << endl; if (_vss == NULL) cerr << Error("Missing GROUND net at top block level." ) << endl;
else destroyRing( _vssi ); else destroyRing( _vss );
}
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 ) bool GlobalNetTable::guessGlobalNet ( const Name& name, Net* net )
{ {
if (name == _vddePadNetName) { if (name == _vddCoreName) {
cmess1 << " - Using <" << net->getName() << "> as corona (external:vdde) power net." << endl; cmess1 << " - Using <" << net->getName() << "> as core (internal:vdd) power net." << endl;
_vdde = net; _vdd = net;
return true; return true;
} }
if (name == _vddiPadNetName) { if (name == _vssCoreName) {
cmess1 << " - Using <" << net->getName() << "> as core (internal:vddi) power net." << endl; cmess1 << " - Using <" << net->getName() << "> as core (internal:vss) ground net." << endl;
_vddi = net; _vss = net;
return true; return true;
} }
if (name == _vssePadNetName) { if (name == _ckCoreName) {
cmess1 << " - Using <" << net->getName() << "> as corona (external:vsse) ground net." << endl; cmess1 << " - Using <" << net->getName() << "> as core (internal:ck) clock net." << endl;
_vsse = net; _ck = net;
return true;
}
if (name == _vssiPadNetName) { if (NetRoutingExtension::isMixedPreRoute(_ck)) {
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)) {
cmess1 << " (core clock net is already routed)" << endl; cmess1 << " (core clock net is already routed)" << endl;
_flags |= ClockIsRouted; _flags |= ClockIsRouted;
} else { } else {
@ -361,12 +239,6 @@ namespace {
return true; return true;
} }
if (name == _ckPadNetName) {
cmess1 << " - Using <" << net->getName() << "> as external chip clock net." << endl;
_ck = net;
return true;
}
return false; return false;
} }
@ -377,11 +249,8 @@ namespace {
if (net == _blockage) return _blockage; if (net == _blockage) return _blockage;
if (_vdde and (net->getName() == _vdde->getName())) return _vdde; if (net->getType() == Net::Type::POWER ) return _vdd;
if (_vsse and (net->getName() == _vsse->getName())) return _vsse; if (net->getType() == Net::Type::GROUND) return _vss;
if (net->getType() == Net::Type::POWER ) return _vddi;
if (net->getType() == Net::Type::GROUND) return _vssi;
if (net->getType() != Net::Type::CLOCK ) { if (net->getType() != Net::Type::CLOCK ) {
return NULL; return NULL;
} }
@ -420,17 +289,12 @@ namespace {
} }
} }
cdebug_log(159,0) << " Check againts top clocks ck:" << ((_ck) ? _ck->getName() : "NULL") cdebug_log(159,0) << " Check againts top clocks ck:"
<< " cki:" << ((_cki) ? _cki->getName() : "NULL") << ((_ck) ? _ck->getName() : "NULL") << endl;
<< " cko:" << ((_cko) ? _cko->getName() : "NULL")
<< endl;
if (_ck and (upNet->getName() == _ck->getName() )) return _ck; if (_ck) {
if (_cki and (upNet->getName() == _cki->getName())) return _cki; if (upNet->getName() == _ck->getName()) {
if (isCoreClockNetRouted(upNet)) return _ck;
if (_cko) {
if (upNet->getName() == _cko->getName()) {
if (isCoreClockNetRouted(upNet)) return _cko;
} }
} }
@ -439,7 +303,7 @@ namespace {
bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const bool GlobalNetTable::isCoreClockNetRouted ( const Net* net ) const
{ return (net == _cko) and (_flags & ClockIsRouted); } { return (net == _ck) and (_flags & ClockIsRouted); }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -1086,7 +950,7 @@ namespace {
, _goMatchCount (0) , _goMatchCount (0)
{ {
setCell ( katana->getCell() ); setCell ( katana->getCell() );
setArea ( katana->getCell()->getBoundingBox() ); setArea ( katana->getCell()->getAbutmentBox() );
setBasicLayer ( NULL ); setBasicLayer ( NULL );
setFilter ( Query::DoTerminalCells|Query::DoComponents ); setFilter ( Query::DoTerminalCells|Query::DoComponents );

View File

@ -270,10 +270,14 @@ namespace {
TrackElement* segment = track->getSegment(i); TrackElement* segment = track->getSegment(i);
if (not segment or segment->isRouted()) continue; if (not segment or segment->isRouted()) continue;
if (segment and segment->isFixed() and segment->isTerminal()) { if (segment and segment->isFixed() and segment->isTerminal()) {
Interval freeInterval = track->getFreeInterval( segment->getSourceU(), segment->getNet() );
DbU::Unit ppitch = segment->getPPitch(); DbU::Unit ppitch = segment->getPPitch();
//DbU::Unit pitch = segment->getPitch(); //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 (freeInterval.getSize() < ppitch*6) {
if ( (segment->getSourceU() - freeInterval.getVMin() < ppitch*3) if ( (segment->getSourceU() - freeInterval.getVMin() < ppitch*3)
or (freeInterval.getVMax() - segment->getTargetU() < ppitch*3) ) { or (freeInterval.getVMax() - segment->getTargetU() < ppitch*3) ) {

View File

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