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:
parent
ce60ed5a30
commit
82dc58bf8e
|
@ -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) );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
<< ",";
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -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'):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ):
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -24,12 +24,6 @@
|
|||
#include "katana/KatanaEngine.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
} // Anonymous namespace.
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
||||
using namespace std;
|
||||
|
|
Loading…
Reference in New Issue