2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
// -*- C++ -*-
|
|
|
|
//
|
|
|
|
// This file is part of the Coriolis Software.
|
|
|
|
// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved
|
|
|
|
//
|
|
|
|
// ===================================================================
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
//
|
|
|
|
// x-----------------------------------------------------------------x
|
|
|
|
// | |
|
|
|
|
// | C O R I O L I S |
|
|
|
|
// | K a t a b a t i c - Routing Toolbox |
|
|
|
|
// | |
|
|
|
|
// | Author : Jean-Paul CHAPUT |
|
|
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
|
|
// | =============================================================== |
|
|
|
|
// | C++ Module : "./LayerAssign.cpp" |
|
|
|
|
// | *************************************************************** |
|
|
|
|
// | U p d a t e s |
|
|
|
|
// | |
|
|
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include "hurricane/Bug.h"
|
|
|
|
#include "hurricane/Warning.h"
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
|
|
#include "hurricane/Net.h"
|
|
|
|
#include "hurricane/NetExternalComponents.h"
|
|
|
|
#include "hurricane/Layer.h"
|
|
|
|
#include "hurricane/RoutingPad.h"
|
|
|
|
#include "hurricane/Pad.h"
|
|
|
|
#include "hurricane/Plug.h"
|
|
|
|
#include "hurricane/Instance.h"
|
|
|
|
#include "hurricane/Vertical.h"
|
|
|
|
#include "hurricane/Horizontal.h"
|
|
|
|
|
|
|
|
#include "crlcore/RoutingGauge.h"
|
|
|
|
|
|
|
|
#include "katabatic/AutoContact.h"
|
|
|
|
#include "katabatic/AutoSegment.h"
|
|
|
|
#include "katabatic/GCellGrid.h"
|
|
|
|
#include "katabatic/KatabaticEngine.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace Katabatic {
|
|
|
|
|
|
|
|
using Hurricane::DebugSession;
|
|
|
|
using Hurricane::ltracein;
|
|
|
|
using Hurricane::ltraceout;
|
|
|
|
using Hurricane::ForEachIterator;
|
|
|
|
using Hurricane::Warning;
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::_splitContactsOfNet ( Net* net )
|
|
|
|
{
|
|
|
|
DebugSession::open ( net, 90 );
|
|
|
|
|
|
|
|
ltrace(100) << "Katabatic::_splitContactsOfNet ( " << net << " )" << endl;
|
|
|
|
ltracein(99);
|
|
|
|
|
|
|
|
Session::invalidate ( net );
|
|
|
|
set<AutoContact*> globalContacts;
|
|
|
|
|
|
|
|
forEach ( Segment*, isegment, net->getSegments() ) {
|
|
|
|
if ( ( (*isegment)->getLayer() == Session::getRoutingLayer(3) )
|
|
|
|
|| ( (*isegment)->getLayer() == Session::getRoutingLayer(4) ) ) {
|
|
|
|
AutoContact* contact = Session::lookup ( dynamic_cast<Contact*>((*isegment)->getSource()) );
|
|
|
|
if ( contact ) globalContacts.insert ( contact );
|
|
|
|
|
|
|
|
contact = Session::lookup ( dynamic_cast<Contact*>((*isegment)->getTarget()) );
|
|
|
|
if ( contact ) globalContacts.insert ( contact );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set<AutoContact*>::iterator it = globalContacts.begin();
|
|
|
|
for ( ; it != globalContacts.end() ; it++ ) {
|
|
|
|
(*it)->split ();
|
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(99);
|
|
|
|
|
|
|
|
DebugSession::close ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
void KatabaticEngine::_desaturate ( unsigned int depth
|
|
|
|
, set<Net*>& globalNets
|
|
|
|
, unsigned long& total
|
|
|
|
, unsigned long& globals )
|
2010-03-09 09:24:29 -06:00
|
|
|
{
|
2010-05-27 11:12:28 -05:00
|
|
|
if ( depth+2 >= Session::getConfiguration()->getAllowedDepth() ) {
|
2010-03-09 09:24:29 -06:00
|
|
|
cerr << Warning("Katabatic::_desaturate(): %s, no remaining upper layers."
|
|
|
|
,getString(Session::getRoutingGauge()->getRoutingLayer(depth)->getName()).c_str()
|
|
|
|
) << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmess1 << " o Desaturate layer "
|
|
|
|
<< Session::getRoutingGauge()->getRoutingLayer(depth)->getName() << endl;
|
|
|
|
|
2010-03-23 04:25:15 -05:00
|
|
|
//vector<GCell*> gcells = *(_gcellGrid->getGCellVector());
|
|
|
|
DyKeyQueue queue ( depth, *(_gcellGrid->getGCellVector()) );
|
|
|
|
vector<GCell*> invalidateds;
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
bool optimized = true;
|
|
|
|
while ( optimized ) {
|
|
|
|
optimized = false;
|
2010-03-23 04:25:15 -05:00
|
|
|
//sort ( gcells.begin(), gcells.end(), GCell::CompareByDensity(depth) );
|
|
|
|
queue.revalidate ();
|
|
|
|
|
|
|
|
std::set<GCell*,GCell::CompareByKey>::const_iterator igcell = queue.getGCells().begin();
|
|
|
|
size_t i = 0;
|
|
|
|
for ( ; igcell!=queue.getGCells().end() ; ++igcell, ++i ) {
|
|
|
|
if ( not (*igcell)->isSaturated ( depth ) ) {
|
|
|
|
ltrace(190) << "STOP desaturated: @" << i << " " << *igcell << endl;
|
|
|
|
for ( ; igcell!=queue.getGCells().end() ; ++igcell ) {
|
|
|
|
if ( (*igcell)->isSaturated ( depth ) ) {
|
|
|
|
cerr << "[ERROR] Still saturated: @" << i << " " << *igcell << endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-05-03 04:16:28 -05:00
|
|
|
ltrace(190) << "step desaturate: @ " << i << " " << *igcell << endl;
|
2010-03-23 04:25:15 -05:00
|
|
|
|
2010-05-03 04:16:28 -05:00
|
|
|
AutoSegment* segment = NULL;
|
2010-03-23 04:25:15 -05:00
|
|
|
optimized = (*igcell)->stepDesaturate ( depth, globalNets, segment );
|
|
|
|
|
|
|
|
if ( segment ) {
|
|
|
|
++total; ++globals;
|
|
|
|
segment->getGCells ( invalidateds );
|
|
|
|
for ( size_t j=0 ; j<invalidateds.size() ; j++ ) {
|
|
|
|
queue.invalidate ( invalidateds[j] );
|
|
|
|
}
|
|
|
|
}
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
if ( optimized ) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::_layerAssignByLength ( Net* net, unsigned long& total, unsigned long& global, set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
DebugSession::open ( net, 90 );
|
|
|
|
|
|
|
|
ltrace(100) << "Katabatic::_layerAssignByLength ( " << net << " )" << endl;
|
|
|
|
ltracein(99);
|
|
|
|
|
|
|
|
bool isGlobal = false;
|
|
|
|
set<AutoContact*> globalContacts;
|
|
|
|
|
|
|
|
forEach ( Segment*, isegment, net->getSegments() ) {
|
|
|
|
total++;
|
|
|
|
if ( (*isegment)->getLength() > getGlobalThreshold() ) {
|
|
|
|
if ( !isGlobal ) {
|
|
|
|
isGlobal = true;
|
|
|
|
globalNets.insert ( net );
|
|
|
|
//cmess2 << " - " << getString(net) << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
global++;
|
|
|
|
if ( (*isegment)->getLayer() == Session::getRoutingLayer(1) ) (*isegment)->setLayer ( Session::getRoutingLayer(3) );
|
|
|
|
if ( (*isegment)->getLayer() == Session::getRoutingLayer(2) ) (*isegment)->setLayer ( Session::getRoutingLayer(4) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ltraceout(99);
|
|
|
|
|
|
|
|
DebugSession::close ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::_layerAssignByLength ( unsigned long& total, unsigned long& global, set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
cmess1 << " o Assign Layer (simple wirelength)." << endl;
|
|
|
|
|
2010-05-11 06:04:23 -05:00
|
|
|
NetSet::iterator inet = _routingNets.begin();
|
|
|
|
for ( ; inet != _routingNets.end() ; ++inet )
|
|
|
|
_layerAssignByLength ( *inet, total, global, globalNets );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::_layerAssignByTrunk ( Net* net, unsigned long& total, unsigned long& global, set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
DebugSession::open ( net, 90 );
|
|
|
|
|
|
|
|
ltrace(100) << "Katabatic::_layerAssignByTrunk ( " << net << " )" << endl;
|
|
|
|
ltracein(99);
|
|
|
|
|
|
|
|
bool isGlobal = false;
|
|
|
|
unsigned long netGlobal = 0;
|
|
|
|
unsigned long netTotal = 0;
|
|
|
|
set<AutoContact*> globalContacts;
|
|
|
|
|
|
|
|
forEach ( Segment*, isegment, net->getSegments() ) {
|
|
|
|
netTotal++;
|
|
|
|
|
|
|
|
if ( (*isegment)->getLength() > getGlobalThreshold() ) {
|
|
|
|
isGlobal = true;
|
|
|
|
netTotal = 0;
|
|
|
|
globalNets.insert ( net );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( isGlobal ) {
|
|
|
|
//cmess2 << " - " << getString(net) << endl;
|
|
|
|
|
|
|
|
forEach ( Segment*, isegment, net->getSegments() ) {
|
|
|
|
netTotal++;
|
|
|
|
|
|
|
|
AutoSegment* autoSegment = Session::lookup ( *isegment );
|
|
|
|
if ( autoSegment && !autoSegment->isTerminal() ) {
|
|
|
|
netGlobal++;
|
|
|
|
|
|
|
|
ltrace(99) << "Migrate to M4/M5: " << autoSegment << endl;
|
|
|
|
if ( autoSegment->isHorizontal() ) autoSegment->setLayer ( Session::getRoutingLayer(3) );
|
|
|
|
if ( autoSegment->isVertical () ) autoSegment->setLayer ( Session::getRoutingLayer(4) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
total += netTotal;
|
|
|
|
global += netGlobal;
|
|
|
|
|
|
|
|
ltraceout(99);
|
|
|
|
|
|
|
|
DebugSession::close ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::_layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& globalNets )
|
|
|
|
{
|
|
|
|
cmess1 << " o Assign Layer (whole net trunk)." << endl;
|
|
|
|
|
2010-05-11 06:04:23 -05:00
|
|
|
NetSet::iterator inet = _routingNets.begin();
|
|
|
|
for ( ; inet != _routingNets.end() ; ++inet )
|
|
|
|
_layerAssignByTrunk ( *inet, total, global, globalNets );
|
2010-03-09 09:24:29 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KatabaticEngine::layerAssign ( unsigned int method )
|
|
|
|
{
|
|
|
|
set<Net*> globalNets;
|
|
|
|
|
|
|
|
unsigned long total = 0;
|
|
|
|
unsigned long global = 0;
|
|
|
|
|
|
|
|
startMeasures ();
|
|
|
|
Session::open ( this );
|
|
|
|
|
|
|
|
switch ( method ) {
|
|
|
|
case LayerAssignByLength: _layerAssignByLength(total,global,globalNets); break;
|
2010-04-12 06:22:11 -05:00
|
|
|
case LayerAssignByTrunk: _layerAssignByTrunk (total,global,globalNets); break;
|
2010-03-09 09:24:29 -06:00
|
|
|
case NoNetLayerAssign: break;
|
|
|
|
default:
|
|
|
|
stopMeasures ();
|
|
|
|
Session::close ();
|
|
|
|
throw Error ( badMethod
|
|
|
|
, "Katabatic::layerAssign()"
|
|
|
|
, method
|
|
|
|
, getString(_cell).c_str()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
set<Net*>::iterator inet = globalNets.begin();
|
|
|
|
for ( ; inet != globalNets.end() ; inet++ )
|
|
|
|
_splitContactsOfNet ( *inet );
|
|
|
|
globalNets.clear ();
|
|
|
|
|
|
|
|
Session::revalidate ();
|
|
|
|
|
|
|
|
for ( int i=0 ; i < 3 ; i++ ) {
|
2010-03-23 04:25:15 -05:00
|
|
|
_desaturate ( 1, globalNets, total, global );
|
|
|
|
_desaturate ( 2, globalNets, total, global );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
globalNets.clear ();
|
|
|
|
|
|
|
|
Session::revalidate ();
|
|
|
|
if ( !_gcellGrid->updateDensity () ) break;
|
|
|
|
}
|
|
|
|
//refresh ( false );
|
|
|
|
|
|
|
|
#if defined(CHECK_DATABASE)
|
|
|
|
_check ( "after layer assignment" );
|
|
|
|
#endif
|
|
|
|
#if defined(CHECK_DETERMINISM)
|
2010-05-11 06:04:23 -05:00
|
|
|
NetSet::iterator inet = _routingNets.begin();
|
|
|
|
for ( ; inet != _routingNets.end() ; inet++ )
|
|
|
|
_print ( *inet );
|
2010-03-09 09:24:29 -06:00
|
|
|
#endif
|
|
|
|
|
2010-04-12 06:22:11 -05:00
|
|
|
// Look for RoutingPad overload.
|
|
|
|
vector<GCell*> gcells = *(_gcellGrid->getGCellVector());
|
|
|
|
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
|
|
|
|
gcells[i]->rpDesaturate ( globalNets );
|
|
|
|
// set<RoutingPad*> rps;
|
|
|
|
// gcells[i]->getRoutingPads ( rps );
|
|
|
|
|
|
|
|
// if ( rps.size() > 7 ) {
|
|
|
|
// cerr << "[WARNING] " << gcells[i] << "has " << rps.size() << " terminals." << endl;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
Session::revalidate ();
|
|
|
|
|
2010-03-09 09:24:29 -06:00
|
|
|
Session::setWarnGCellOverload ( true );
|
|
|
|
_gcellGrid->checkDensity ();
|
|
|
|
|
|
|
|
Session::close ();
|
|
|
|
|
|
|
|
stopMeasures ();
|
2010-04-17 05:14:22 -05:00
|
|
|
printMeasures ( "assign" );
|
2010-03-09 09:24:29 -06:00
|
|
|
|
|
|
|
cmess2 << " - Total segments : " << total << endl;
|
|
|
|
cmess2 << " - Global segments : " << global << endl;
|
|
|
|
cmess2 << " - Ratio : "
|
|
|
|
<< ((float)global/(float)total)*100.0 << "%." << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // End of Katabatic namespace.
|