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;
|
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) );
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
<< ",";
|
<< ",";
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
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:
|
||||||
|
|
|
@ -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'):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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.
|
# 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
|
@ -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) ) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue