2010-03-09 09:23:58 -06:00
//
// This file is part of the Coriolis Project.
// Copyright (C) Laboratoire LIP6 - Departement ASIM
// Universite Pierre et Marie Curie
//
// Main contributors :
// Christophe Alexandre <Christophe.Alexandre@lip6.fr>
// Hugo Cl<43> ment <Hugo.Clement@lip6.fr>
// Jean-Paul Chaput <Jean-Paul.Chaput@lip6.fr>
// Christian Masson <Christian.Masson@lip6.fr>
//
// The Coriolis Project is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// The Coriolis Project is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with the Coriolis Project; if not, write to the Free Software
// Foundation, inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//
// License-Tag
//
//
// Date : 30/10/2006
// Author : Damien Dupuis <Damien.Dupuis@lip6.fr>
//
// Authors-Tag
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | Alliance / Hurricane Interface |
// | |
// | Author : Damien DUPUIS |
// | E-mail : Damien.Dupuis.lip6.fr |
// | =============================================================== |
// | C++ Module : "./Knik.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
# include <climits>
2010-05-11 06:03:50 -05:00
# include "hurricane/Warning.h"
2010-03-09 09:23:58 -06:00
# include "hurricane/RoutingPad.h"
# include "hurricane/Property.h"
# include "hurricane/Contact.h"
# include "hurricane/Horizontal.h"
# include "hurricane/Vertical.h"
# include "hurricane/Cell.h"
# include "hurricane/Technology.h"
# include "hurricane/DataBase.h"
# include "hurricane/UpdateSession.h"
# include "hurricane/Breakpoint.h"
# include "crlcore/Utilities.h"
# include "crlcore/ToolBox.h"
2010-04-23 08:13:22 -05:00
# include "crlcore/Measures.h"
2010-08-22 07:37:08 -05:00
# include "crlcore/RoutingGauge.h"
# include "crlcore/RoutingLayerGauge.h"
# include "crlcore/AllianceFramework.h"
2010-03-09 09:23:58 -06:00
# include "knik/Configuration.h"
# include "knik/Edge.h"
# include "knik/Vertex.h"
# include "knik/Graph.h"
# include "knik/RoutingGrid.h"
# include "knik/NetExtension.h"
# include "knik/KnikEngine.h"
# define MAX_RUNTIME 86400
# define MAX_ITERATION UINT_MAX
namespace Knik {
2010-05-11 06:03:50 -05:00
using Hurricane : : Warning ;
2010-04-23 08:13:22 -05:00
using CRL : : addMeasure ;
2010-08-22 07:37:08 -05:00
using CRL : : RoutingGauge ;
using CRL : : RoutingLayerGauge ;
using CRL : : AllianceFramework ;
2010-04-23 08:13:22 -05:00
2010-03-09 09:23:58 -06:00
//globale variables
unsigned __congestion__ ;
unsigned __precongestion__ ;
float __edge_cost__ ;
bool __initialized__ ;
extern bool __ripupMode__ ;
const Name KnikEngine : : _toolName = " Knik::KnikEngine " ;
float KnikEngine : : _edgeCapacityPercent = 1.0 ;
KnikEngine : : KnikEngine ( Cell * cell , unsigned congestion , unsigned precongestion , bool benchMode , bool useSegments , float edgeCost )
// *********************************************************************************************************************************
: Inherit ( cell )
, _routingGraph ( NULL )
, _routingGrid ( NULL )
, _benchMode ( benchMode )
, _useSegments ( useSegments )
, _routingDone ( false )
, _rerouteIteration ( 0 )
, _segmentOverEdges ( )
, _sortSegmentOv ( )
{
if ( congestion > 1 )
throw Error ( " KnikEngine::KnikEngine(): congestion argument must be 0 (None) or 1 (Congestion) : %s. "
, getString ( congestion ) . c_str ( ) ) ;
__congestion__ = congestion ;
if ( precongestion > 2 )
throw Error ( " KnikEngine::KnikEngine(): precongestion argument must be 0 (None), 1 (Static) or 2 (Dynamic) : %s. "
, getString ( precongestion ) . c_str ( ) ) ;
__precongestion__ = precongestion ;
__edge_cost__ = edgeCost ;
__initialized__ = false ;
}
KnikEngine : : ~ KnikEngine ( )
// ***********************
{
}
KnikEngine * KnikEngine : : create ( Cell * cell , unsigned congestion , unsigned precongestion , bool benchMode , bool useSegments , float edgeCost )
// *****************************************************************************************************************************************
{
CRL : : deleteEmptyNets ( cell ) ;
KnikEngine * _knik = new KnikEngine ( cell , congestion , precongestion , benchMode , useSegments , edgeCost ) ;
_knik - > _postCreate ( ) ;
2010-05-29 09:08:29 -05:00
cout < < " o Knik -- Global router makes use of FLUTE software " < < endl ;
cout < < Dots : : asIdentifier ( " - Author " , " Chris C. N. CHU " ) < < endl ;
cout < < Dots : : asIdentifier ( " - Prof. Ident. " , " Iowa State University " ) < < endl ;
cout < < Dots : : asIdentifier ( " - URL " , " http://home.eng.iastate.edu/~cnchu " ) < < endl ;
2010-03-09 09:23:58 -06:00
return _knik ;
}
void KnikEngine : : _postCreate ( )
// ***************************
{
Inherit : : _postCreate ( ) ;
// For Flute : readLUT to be able to use POWV9.dat & POST9.dat
readLUT ( ) ;
return ;
}
void KnikEngine : : destroy ( )
// ***********************
{
_preDestroy ( ) ;
delete this ;
}
void KnikEngine : : _preDestroy ( )
// ***************************
{
_routingGraph - > destroy ( ) ;
Inherit : : _preDestroy ( ) ;
//Configuration::get()->destroy();
return ;
}
void KnikEngine : : MakeRoutingLeaves ( )
// *********************************
{
//unsigned steps = getCell()->getAbutmentBox().getHeight() / DbU::lambda(50); // +o( mieux vaudrait recuperer le slice !
//if ( _nimbus->getDepth() < steps ) {
// _nimbus->progress ( steps - _nimbus->getDepth() );
// _nimbus->PlacementLeavesDown();
//}
// for_each_gcell(gcell, _nimbus->getPlacementLeaves()) {
// //if (_metisseLimit) // dans un premier temps on se limite <20> respecter les placementLeaves (on ne descend pas en dessous)
// if (gcell->isAStrictSubGCellOf(gcell->getPlacementLeaf()))
// break;
// gcell->setAsRoutingLeaf();
// for_each_fence (fence, gcell->getSurroundingFences()) {
// fence->setAsRoutingFence();
// end_for;
// }
// end_for;
// }
return ;
}
void KnikEngine : : initGlobalRouting ( )
// *********************************
{
assert ( _nets_to_route . empty ( ) ) ;
cmess2 < < " o Knik::initGlobalRouting() " < < endl ;
//#if defined(__USE_STATIC_PRECONGESTION__) || defined(__USE_DYNAMIC_PRECONGESTION__)
cmess2 < < " - Congestion: " < < __congestion__ < < endl ;
cmess2 < < " - PreCongestion: " < < __precongestion__ < < endl ;
cmess2 < < " - EdgeCost: " < < __edge_cost__ < < endl ;
//#endif
// create the route graph
if ( ! _routingGraph ) {
_timer . resetIncrease ( ) ;
_timer . start ( ) ;
cmess2 < < " o create routing graph " < < endl ;
Cell * cell = getCell ( ) ;
_routingGraph = Graph : : create ( cell , _routingGrid , _benchMode , _useSegments ) ;
cmess2 < < " - Graph size: " < < _routingGraph - > getXSize ( )
< < " x " < < _routingGraph - > getYSize ( ) < < endl ;
_timer . stop ( ) ;
printTime ( ) ;
}
else {
cmess2 < < " routingGraph already exists ! " < < endl ;
}
// 20/02/09 tout ce qui suit dans la fonction etait inclu dans le if(!_routingGraph) on le sépare pour pouvoir
// créer explicitement le graph dans une fonction, pour
_timer . resetIncrease ( ) ;
_timer . start ( ) ;
cmess2 < < " o Selecting nets to route and create precongestion " < < endl ;
2010-05-11 06:03:50 -05:00
const unsigned int MaxDegree = 13000 ;
2010-03-09 09:23:58 -06:00
Name obstacleNetName ( " obstaclenet " ) ;
2010-05-11 06:03:50 -05:00
2010-03-09 09:23:58 -06:00
//for_each_occurrence ( occurrence, cell->getHyperNetRootNetOccurrences() ) // working on deepNets
for_each_net ( net , getCell ( ) - > getNets ( ) ) {
//Net* net = dynamic_cast<Net*>(occurrence.getEntity()); // working on deepNets
assert ( net ) ;
//cerr << " Net : " << net << endl;
if ( net - > isGlobal ( )
or net - > isSupply ( )
or net - > isClock ( )
or ( net - > getName ( ) = = obstacleNetName ) ) {
2010-05-11 06:03:50 -05:00
cmess1 < < " - < " < < net - > getName ( ) < < " > not routed (global, supply, clock or obstacle). " < < endl ;
continue ;
2010-03-09 09:23:58 -06:00
}
//if ( !isVeryFlatCell && net->getCell()->isLeaf() ) { // Don't want to route Leaf Cells nets
// //cerr << " rootNet belongs to a leaf cell => continue" << endl;
// continue;
//} // working on deepNets
2010-05-11 06:03:50 -05:00
// We want to route nets with more at least 2 and less than MaxDegree vertexes
2010-03-09 09:23:58 -06:00
unsigned netDegree = _routingGraph - > countVertexes ( net ) ;
2010-05-11 06:03:50 -05:00
if ( netDegree > 1 & & netDegree < MaxDegree ) {
2010-03-09 09:23:58 -06:00
Box bbox = net - > getBoundingBox ( ) ;
NetRecord record ( net , ( long int ) ( ( DbU : : getLambda ( bbox . getWidth ( ) ) + 1 ) * ( DbU : : getLambda ( bbox . getHeight ( ) ) + 1 ) ) ) ;
assert ( record . _net ) ;
assert ( record . _exArea > 0 ) ;
_nets_to_route . push_back ( record ) ;
//#if defined(__USE_STATIC_PRECONGESTION__) || defined(__USE_DYNAMIC_PRECONGESTION__)
if ( __precongestion__ )
_routingGraph - > UpdateEstimateCongestion ( true ) ;
//#endif
//cerr << " will be routed." << endl;
}
2010-05-11 06:03:50 -05:00
else {
if ( netDegree > MaxDegree - 1 )
cmess1 < < Warning ( " %s has a not a degree in [2:%u[ (%d), not routed. "
, getString ( net ) . c_str ( ) , MaxDegree , netDegree ) < < endl ;
}
2010-03-09 09:23:58 -06:00
_routingGraph - > resetVertexes ( ) ;
end_for ;
}
stable_sort ( _nets_to_route . begin ( ) , _nets_to_route . end ( ) , NetSurfacesComp ( ) ) ;
NetVector : : iterator new_end = unique ( _nets_to_route . begin ( ) , _nets_to_route . end ( ) ) ;
_nets_to_route . erase ( new_end , _nets_to_route . end ( ) ) ;
_timer . stop ( ) ;
printTime ( ) ;
cmess2 < < " + Nets to route: " < < _nets_to_route . size ( ) < < endl ;
//#endif
// 20/02/09 fin de l'ancienne inclusion
__initialized__ = true ;
}
2010-04-23 08:13:22 -05:00
void KnikEngine : : createRoutingGrid ( unsigned nbXTiles
, unsigned nbYTiles
, const Box & boundingBox
, DbU : : Unit tileWidth
, DbU : : Unit tileHeight
, unsigned hcapacity
, unsigned vcapacity )
2010-03-09 09:23:58 -06:00
{
2010-04-23 08:13:22 -05:00
_routingGrid = RoutingGrid : : create ( nbXTiles
, nbYTiles
, boundingBox
, tileWidth
, tileHeight
, hcapacity
, vcapacity ) ;
2010-03-09 09:23:58 -06:00
}
2010-04-23 08:13:22 -05:00
2010-03-09 09:23:58 -06:00
void KnikEngine : : createRoutingGraph ( )
// **********************************
{
Cell * cell = getCell ( ) ;
_routingGraph = Graph : : create ( cell , _routingGrid , _benchMode , _useSegments ) ;
2010-11-16 07:59:03 -06:00
//Breakpoint::stop ( 0, "Point d'arret:<br> <b>createGlobalGraph()</b> "
// "after Knik createGlobalGraph()." );
2010-03-09 09:23:58 -06:00
}
void KnikEngine : : addRoutingPadToGraph ( RoutingPad * routingPad )
// *************************************************************
{
Vertex * rpVertex = _routingGraph - > getVertex ( routingPad - > getCenter ( ) ) ;
Contact * rpContact = rpVertex - > getContact ( ) ;
if ( ! rpContact | | ( rpContact - > getNet ( ) ! = routingPad - > getNet ( ) ) ) {
Contact * contact = Contact : : create ( routingPad - > getNet ( )
, DataBase : : getDB ( ) - > getTechnology ( ) - > getLayer ( " metal2 " )
, DbU : : lambda ( floor ( DbU : : getLambda ( rpVertex - > getPosition ( ) . getX ( ) ) ) )
, DbU : : lambda ( floor ( DbU : : getLambda ( rpVertex - > getPosition ( ) . getY ( ) ) ) )
, rpVertex - > getHalfWidth ( ) / 5
, rpVertex - > getHalfHeight ( ) / 5
) ;
rpVertex - > setContact ( contact ) ;
}
}
2010-11-16 07:59:03 -06:00
Edge * KnikEngine : : getEdge ( unsigned col1 , unsigned row1 , unsigned col2 , unsigned row2 )
// *************************************************************************************
{
return _routingGraph - > getEdge ( col1 , row1 , col2 , row2 ) ;
}
2010-03-09 09:23:58 -06:00
void KnikEngine : : updateEdgeCapacity ( unsigned col1 , unsigned row1 , unsigned col2 , unsigned row2 , unsigned capacity )
// ******************************************************************************************************************
{
_routingGraph - > UpdateEdgeCapacity ( col1 , row1 , col2 , row2 , capacity ) ;
}
void KnikEngine : : increaseEdgeCapacity ( unsigned col1 , unsigned row1 , unsigned col2 , unsigned row2 , int capacity )
// ***************************************************************************************************************
{
_routingGraph - > increaseEdgeCapacity ( col1 , row1 , col2 , row2 , capacity ) ;
}
void KnikEngine : : insertSegment ( Segment * segment )
// ************************************************
{
_routingGraph - > insertSegment ( segment ) ;
}
Vertex * KnikEngine : : getVertex ( Point position )
// *********************************************
{
return _routingGraph - > getVertex ( position ) ;
}
Vertex * KnikEngine : : getVertex ( DbU : : Unit x , DbU : : Unit y )
// *******************************************************
{
return _routingGraph - > getVertex ( x , y ) ;
}
void KnikEngine : : printTime ( )
// *************************
{
cmess2 < < " + Done in " < < Timer : : getStringTime ( _timer . getCombTime ( ) )
< < " [+ " < < Timer : : getStringMemory ( _timer . getIncrease ( ) ) < < " ]. " < < endl ;
cmess2 < < " (raw measurements : " < < _timer . getCombTime ( )
< < " s [+ " < < ( _timer . getIncrease ( ) > > 10 ) < < " Ko/ "
< < ( _timer . getMemorySize ( ) > > 10 ) < < " Ko]) " < < endl ;
2010-04-23 08:13:22 -05:00
2010-03-09 09:23:58 -06:00
}
// void KnikEngine::showEstimateOccupancy()
// // *************************************
// {
// if ( _routingGraph )
// _routingGraph->UpdateEstimateOccupancyWindow();
// }
inline bool netId_sort ( Net * net1 , Net * net2 ) { return NetExtension : : getId ( net1 ) < NetExtension : : getId ( net2 ) ; }
string KnikEngine : : _getSolutionName ( ) const
// ****************************************
{
return getString ( _cell - > getName ( ) ) + " .kgr " ;
}
void KnikEngine : : saveSolution ( const string & fileName )
// *****************************************************
{
Name obstacleNetName ( " obstaclenet " ) ;
string saveFileName = fileName ;
if ( saveFileName . empty ( ) )
saveFileName = _getSolutionName ( ) ;
_nets_to_route . clear ( ) ;
vector < Net * > all_nets ;
forEach ( Net * , net , _cell - > getNets ( ) ) {
if ( net - > isGlobal ( )
or net - > isSupply ( )
or net - > isClock ( )
or ( net - > getName ( ) = = obstacleNetName ) ) continue ;
all_nets . push_back ( * net ) ;
}
stable_sort ( all_nets . begin ( ) , all_nets . end ( ) , netId_sort ) ;
CRL : : IoFile saveStream ( saveFileName ) ;
saveStream . open ( " w " ) ;
FILE * saveFile = saveStream . getFile ( ) ;
if ( ! saveFile )
throw Error ( " Cannot open solution file to write ! " ) ;
2010-11-16 07:59:03 -06:00
const Layer * gcontact = Configuration : : getGContact ( ) ;
const Layer * gmetalh = Configuration : : getGMetalH ( ) ;
const Layer * gmetalv = Configuration : : getGMetalV ( ) ;
for ( size_t i = 0 ; i < all_nets . size ( ) ; + + i ) {
2010-03-09 09:23:58 -06:00
Net * net = all_nets [ i ] ;
long netId = NetExtension : : getId ( net ) ;
//assert ( netId >= 0 );
2010-11-16 07:59:03 -06:00
2010-03-09 09:23:58 -06:00
vector < Contact * > viaContacts ;
2010-11-16 07:59:03 -06:00
forEach ( Contact * , icontact , net - > getContacts ( ) ) {
if ( ( icontact - > getLayer ( ) = = gcontact ) or ( icontact - > getLayer ( ) = = gmetalv ) )
viaContacts . push_back ( * icontact ) ;
2010-03-09 09:23:58 -06:00
}
2010-11-16 07:59:03 -06:00
vector < Segment * > grSegments ;
forEach ( Segment * , isegment , net - > getSegments ( ) ) {
if ( ( isegment - > getLayer ( ) = = gmetalh ) or ( isegment - > getLayer ( ) = = gmetalv ) ) {
grSegments . push_back ( * isegment ) ;
}
}
unsigned nbEntries = grSegments . size ( ) + viaContacts . size ( ) ;
2010-03-09 09:23:58 -06:00
fprintf ( saveFile , " %s %ld %d \n " , getString ( net - > getName ( ) ) . c_str ( ) , netId , nbEntries ) ;
2010-11-16 07:59:03 -06:00
for ( size_t j = 0 ; j < grSegments . size ( ) ; + + j ) {
unsigned layer = ( dynamic_cast < Horizontal * > ( grSegments [ j ] ) ) ? 1 : 2 ;
fprintf ( saveFile , " (%d,%d,%d)-(%d,%d,%d) \n "
, ( unsigned ) DbU : : getLambda ( grSegments [ j ] - > getSourceX ( ) )
, ( unsigned ) DbU : : getLambda ( grSegments [ j ] - > getSourceY ( ) )
, layer
, ( unsigned ) DbU : : getLambda ( grSegments [ j ] - > getTargetX ( ) )
, ( unsigned ) DbU : : getLambda ( grSegments [ j ] - > getTargetY ( ) )
, layer
) ;
//if ( layer == 2 ) { // pour rajouter les vias de descentes aux connecteurs
// if ( segment->getSource()->getLayer() == layerGMetalV ) {
// unsigned x = (unsigned)DbU::getLambda(segment->getSourceX());
// unsigned y = (unsigned)DbU::getLambda(segment->getSourceY());
// fprintf(saveFile, "(%d,%d,1)-(%d,%d,2)\n", x, y, x, y);
// }
// if ( segment->getTarget()->getLayer() == layerGMetalV ) {
// unsigned x = (unsigned)DbU::getLambda(segment->getTargetX());
// unsigned y = (unsigned)DbU::getLambda(segment->getTargetY());
// fprintf(saveFile, "(%d,%d,1)-(%d,%d,2)\n", x, y ,x, y);
// }
//}
2010-03-09 09:23:58 -06:00
}
2010-11-16 07:59:03 -06:00
for ( size_t i = 0 ; i < viaContacts . size ( ) ; i + + ) {
Contact * contact = viaContacts [ i ] ;
fprintf ( saveFile , " (%d,%d,1)-(%d,%d,2) \n "
, ( unsigned ) DbU : : getLambda ( contact - > getX ( ) )
, ( unsigned ) DbU : : getLambda ( contact - > getY ( ) )
, ( unsigned ) DbU : : getLambda ( contact - > getX ( ) )
, ( unsigned ) DbU : : getLambda ( contact - > getY ( ) )
) ;
2010-03-09 09:23:58 -06:00
}
fprintf ( saveFile , " ! \n " ) ;
}
saveStream . close ( ) ;
}
void KnikEngine : : getHorizontalCutLines ( vector < DbU : : Unit > & horizontalCutLines )
// *****************************************************************************
{
_routingGraph - > getHorizontalCutLines ( horizontalCutLines ) ;
}
void KnikEngine : : getVerticalCutLines ( vector < DbU : : Unit > & verticalCutLines )
// *************************************************************************
{
_routingGraph - > getVerticalCutLines ( verticalCutLines ) ;
}
void KnikEngine : : unrouteSelected ( )
// *******************************
{
// static const Layer* layerGAlu2 = NULL;
// static const Layer* layerGAlu3 = NULL;
// static const Layer* layerGCont = NULL;
// if ( !layerGAlu2 ) {
// Technology* technology = DataBase::getDB()->getTechnology();
// layerGAlu2 = technology->getLayer(Name("GALU2"));
// layerGAlu3 = technology->getLayer(Name("GALU3"));
// layerGCont = technology->getLayer(Name("GCONTACT"));
// }
// set<Segment*> segmentsToUnroute;
// CEditor* editor = getCEditor ( getCell() );
// if (editor->hasSomethingSelected() ) {
// for_each_selector ( selector, editor->getSelectors() ) {
// if ( Segment* segment = dynamic_cast<Segment*>(selector->getOccurrence().getEntity()) ) {
// Layer* layer = segment->getLayer();
// if ( (layer == layerGAlu2) || (layer == layerGAlu3) || (layer == layerGCont) ) {
// //cerr << "segment " << segment << " passes " << _routingGraph->getCongestEdgeNb(segment) << endl;
// segmentsToUnroute.insert ( segment );
// }
// }
// end_for;
// }
// }
// UpdateSession::open();
// // Previous call to recursive function
// //while ( !segmentsToUnroute.empty() ) {
// // Segment* seg = (*segmentsToUnroute.begin());
// // unroute ( seg, segmentsToUnroute );
// //}
// do {
// set<Contact*> contacts;
// while ( !segmentsToUnroute.empty() ) { // on parcourt tous les segments a derouter
// Segment* segment = (*segmentsToUnroute.begin());
// if ( !dynamic_cast<Contact*>(segment->getSource()) ) throw Error ( "unroute segment : segment's source is not a contact !" );
// if ( !dynamic_cast<Contact*>(segment->getTarget()) ) throw Error ( "unroute segment : segment's target is not a contact !" );
// // on insere les contacts source et target dans le set
// contacts.insert ( static_cast<Contact*>(segment->getSource()) );
// contacts.insert ( static_cast<Contact*>(segment->getTarget()) );
// segmentsToUnroute.erase ( segment ); // suppression du segment dans le set
// _routingGraph->removeSegment ( segment ); // il faut mettre a jour les occupations des edges dans le graph !
// segment->getSourceHook()->detach();
// segment->getTargetHook()->detach();
// segment->destroy(); // delete du segment
// }
// for ( set<Contact*>::iterator cit = contacts.begin(); cit != contacts.end() ; cit++ ) { // pour chacun des contacts du set
// Contact* contact = (*cit);
// Vertex* contactVertex = _routingGraph->getVertex(contact->getCenter());
// Hook* contactHook = contact->getBodyHook();
// bool routingPadPresent = false;
// Hook* currentHook = contactHook->getNextHook();
// // on verifie si le contact est associe a un routingPad
// while ( currentHook != contactHook ) {
// if ( dynamic_cast<RoutingPad*>(currentHook->getComponent()) ) {
// RoutingPad* rp = static_cast<RoutingPad*>(currentHook->getComponent());
// if ( _routingGraph->getVertex(rp->getCenter()) == contactVertex ) {
// routingPadPresent = true;
// break;
// }
// }
// currentHook = currentHook->getNextHook();
// }
// // si le contact est associe a un routingPad, on passe au contact suivant
// if ( routingPadPresent ) continue;
// unsigned nbSegments = contact->getSlaveComponents().getSize();
// // sinon s'il a au moins 2 segments on passe au suivant aussi
// if ( nbSegments >= 2 ) continue;
// // sinon s'il n'a qu'un segment, on ajoutele segment au set des segments a derouter
// if ( nbSegments == 1 ) {
// if ( !dynamic_cast<Segment*>(contact->getSlaveComponents().getFirst()) ) throw Error ("somthing else than a segment is on a contact ...");
// segmentsToUnroute.insert(static_cast<Segment*>(contact->getSlaveComponents().getFirst()));
// continue;
// }
// // sinon sile contact est "seul", on le delete, apres vérif tout de meme
// if ( nbSegments == 0 ) {
// contactVertex->setContact( NULL ); // pour etre surqu'on ne pointe pas sur un objet efface
// contact->destroy();
// }
// }
// } while ( !segmentsToUnroute.empty() );
// UpdateSession::close();
// editor->UnselectAll();
// editor->Refresh();
}
string KnikEngine : : adaptString ( string s )
// ****************************************
{
string adapt = s ;
unsigned pos = adapt . find ( ' < ' ) ;
while ( pos < adapt . size ( ) ) {
adapt . replace ( pos , 1 , " < " ) ;
pos = adapt . find ( ' < ' , pos ) ;
}
pos = adapt . find ( ' > ' ) ;
while ( pos < adapt . size ( ) ) {
adapt . replace ( pos , 1 , " > " ) ;
pos = adapt . find ( ' > ' , pos ) ;
}
return adapt ;
}
void KnikEngine : : unrouteOvSegments ( )
// *********************************
{
cmess2 < < " o Unroute overflowed segments : " < < endl ;
unsigned countSegments = 0 ;
unsigned countContacts = 0 ;
UpdateSession : : open ( ) ;
_timer . resume ( ) ;
do {
set < Contact * > contacts ;
while ( ! _segmentsToUnroute . empty ( ) ) { // on parcourt tous les segments a derouter
Segment * segment = ( * _segmentsToUnroute . begin ( ) ) ;
assert ( segment ) ;
if ( ! dynamic_cast < Contact * > ( segment - > getSource ( ) ) )
throw Error ( " unroute segment : segment's source is not a contact ! " ) ;
if ( ! dynamic_cast < Contact * > ( segment - > getTarget ( ) ) )
throw Error ( " unroute segment : segment's target is not a contact ! " ) ;
// on insere les contacts source et target dans le set
contacts . insert ( static_cast < Contact * > ( segment - > getSource ( ) ) ) ;
contacts . insert ( static_cast < Contact * > ( segment - > getTarget ( ) ) ) ;
_segmentsToUnroute . erase ( segment ) ; // suppression du segment dans le set
_routingGraph - > removeSegment ( segment ) ; // il faut mettre a jour les occupations des edges dans le graph !
countSegments + + ;
segment - > getSourceHook ( ) - > detach ( ) ;
segment - > getTargetHook ( ) - > detach ( ) ;
segment - > destroy ( ) ; // delete du segment
}
for ( set < Contact * > : : iterator cit = contacts . begin ( ) ; cit ! = contacts . end ( ) ; cit + + ) { // pour chacun des contacts du set
Contact * contact = ( * cit ) ;
Vertex * contactVertex = _routingGraph - > getVertex ( contact - > getCenter ( ) ) ;
Hook * contactHook = contact - > getBodyHook ( ) ;
bool routingPadPresent = false ;
Hook * currentHook = contactHook - > getNextHook ( ) ;
// on verifie si le contact est associe a un routingPad
while ( currentHook ! = contactHook ) {
if ( dynamic_cast < RoutingPad * > ( currentHook - > getComponent ( ) ) ) {
RoutingPad * rp = static_cast < RoutingPad * > ( currentHook - > getComponent ( ) ) ;
if ( _routingGraph - > getVertex ( rp - > getCenter ( ) ) = = contactVertex ) {
routingPadPresent = true ;
break ;
}
}
currentHook = currentHook - > getNextHook ( ) ;
}
// si le contact est associe a un routingPad, on passe au contact suivant
if ( routingPadPresent ) continue ;
unsigned nbSegments = contact - > getSlaveComponents ( ) . getSize ( ) ;
// sinon s'il a plus de 2 segments on passe au suivant aussi
if ( nbSegments > 2 ) continue ;
// s'il y a 2 segments
if ( nbSegments = = 2 ) {
// s'ils sont de meme direction : on les fusionne
Segment * segment1 = NULL ;
Segment * segment2 = NULL ;
forEach ( Component * , component , contact - > getSlaveComponents ( ) ) {
if ( ! dynamic_cast < Segment * > ( * component ) )
throw Error ( " I did did see a pussy cat " ) ;
Segment * segment = static_cast < Segment * > ( * component ) ;
if ( ! segment1 )
segment1 = segment ;
else if ( ! segment2 )
segment2 = segment ;
else
throw Error ( " Houston we've got a problem " ) ;
}
// on remove les 2 segments dans le graphe pour que les occupations et les références dans les edges soient correctes!
if ( dynamic_cast < Horizontal * > ( segment1 ) & & dynamic_cast < Horizontal * > ( segment2 ) ) {
//cerr << "On remplace : " << segment1 << " et " << segment2 << " par:" << endl;
_routingGraph - > removeSegment ( segment1 ) ;
_routingGraph - > removeSegment ( segment2 ) ;
Horizontal * horiz1 = static_cast < Horizontal * > ( segment1 ) ;
Horizontal * horiz2 = static_cast < Horizontal * > ( segment2 ) ;
assert ( horiz1 - > getNet ( ) = = horiz2 - > getNet ( ) ) ;
Contact * toDel = NULL ;
if ( horiz1 - > getSourceX ( ) < horiz2 - > getSourceX ( ) ) {
Contact * target = dynamic_cast < Contact * > ( horiz2 - > getTarget ( ) ) ;
toDel = dynamic_cast < Contact * > ( horiz1 - > getTarget ( ) ) ;
if ( ! target | | ! toDel )
throw Error ( " Mummy help me ! " ) ;
Hook * hook = horiz1 - > getTargetHook ( ) ;
hook - > detach ( ) ;
hook - > attach ( target - > getBodyHook ( ) ) ;
}
else {
Contact * source = dynamic_cast < Contact * > ( horiz2 - > getSource ( ) ) ;
toDel = dynamic_cast < Contact * > ( horiz1 - > getSource ( ) ) ;
if ( ! source | | ! toDel )
throw Error ( " It's not my fault " ) ;
Hook * hook = horiz1 - > getSourceHook ( ) ;
hook - > detach ( ) ;
hook - > attach ( source - > getBodyHook ( ) ) ;
}
// il est tres important de verifier que le segment qui va etre implicitement detruit n'est pas présent dans _segmentsToUnroute !
set < Segment * > : : iterator horiz2it = _segmentsToUnroute . find ( horiz2 ) ;
if ( horiz2it ! = _segmentsToUnroute . end ( ) ) {
//throw Error ("Implicity destroying a horizontal segment that is present in _segmentToUnroute !");
_segmentsToUnroute . erase ( horiz2it ) ; // doit-on rajouter horiz1 dans _segmentsToUnroute ?
_segmentsToUnroute . insert ( horiz1 ) ; // oui puique horiz2 y était et que horiz1 remplace en partie horiz2
}
toDel - > destroy ( ) ; // le segment horiz2 s'appuie sur le contact et il est donc destroy implicitement
//cerr << " " << segment1 << endl;
// on rajoute le segment1 agrandi dans le graphe, toujours pour les edges A NE FAIRE QUE SI LES SEG SONT DE MEME TYPE
_routingGraph - > insertSegment ( segment1 ) ;
}
else if ( dynamic_cast < Vertical * > ( segment1 ) & & dynamic_cast < Vertical * > ( segment2 ) ) {
//cerr << "On remplace : " << segment1 << " et " << segment2 << " par:" << endl;
_routingGraph - > removeSegment ( segment1 ) ;
_routingGraph - > removeSegment ( segment2 ) ;
Vertical * verti1 = static_cast < Vertical * > ( segment1 ) ;
Vertical * verti2 = static_cast < Vertical * > ( segment2 ) ;
assert ( verti1 - > getNet ( ) = = verti2 - > getNet ( ) ) ;
Contact * toDel = NULL ;
if ( verti1 - > getSourceY ( ) < verti2 - > getSourceY ( ) ) {
Contact * target = dynamic_cast < Contact * > ( verti2 - > getTarget ( ) ) ;
toDel = dynamic_cast < Contact * > ( verti1 - > getTarget ( ) ) ;
if ( ! target | | ! toDel )
throw Error ( " Not again! " ) ;
Hook * hook = verti1 - > getTargetHook ( ) ;
hook - > detach ( ) ;
hook - > attach ( target - > getBodyHook ( ) ) ;
}
else {
Contact * source = dynamic_cast < Contact * > ( verti2 - > getSource ( ) ) ;
toDel = dynamic_cast < Contact * > ( verti1 - > getSource ( ) ) ;
if ( ! source | | ! toDel )
throw Error ( " Please reboot computer ... or not. " ) ;
Hook * hook = verti1 - > getSourceHook ( ) ;
hook - > detach ( ) ;
hook - > attach ( source - > getBodyHook ( ) ) ;
}
// il est tres important de verifier que le segment qui va etre implicitement detruit n'est pas présent dans _segmentsToUnroute !
set < Segment * > : : iterator verti2it = _segmentsToUnroute . find ( verti2 ) ;
if ( verti2it ! = _segmentsToUnroute . end ( ) ) {
//throw Error ("Implicity destroying a vertical segment that is present in _segmentToUnroute !");
_segmentsToUnroute . erase ( verti2it ) ;
_segmentsToUnroute . insert ( verti1 ) ;
}
toDel - > destroy ( ) ; // le segment verti2 s'appuie sur le contact et il est donc destroy implicitement
//cerr << " " << segment1 << endl;
// on rajoute le segment1 agrandi dans le graphe, toujours pour les edges A NE FAIRE QUE SI LES SEG SONT DE MEME TYPE
_routingGraph - > insertSegment ( segment1 ) ;
}
// sinon on continue
else
continue ;
}
// sinon s'il n'a qu'un segment, on ajoute le segment au set des segments a derouter
if ( nbSegments = = 1 ) {
if ( ! dynamic_cast < Segment * > ( contact - > getSlaveComponents ( ) . getFirst ( ) ) )
throw Error ( " somthing else than a segment is on a contact ... " ) ;
_segmentsToUnroute . insert ( static_cast < Segment * > ( contact - > getSlaveComponents ( ) . getFirst ( ) ) ) ; // XXX euh oui mais s'il est déjà présent dans le set ? il se passe quoi ? XXX
continue ;
}
// sinon si le contact est "seul", on le delete, apres vérif tout de meme
if ( nbSegments = = 0 ) {
contactVertex - > setContact ( NULL ) ; // pour etre surqu'on ne pointe pas sur un objet efface
contact - > destroy ( ) ;
countContacts + + ;
}
}
} while ( ! _segmentsToUnroute . empty ( ) ) ;
_timer . suspend ( ) ;
cmess2 < < " + Done in " < < _timer . getCombTime ( )
< < " s [+ " < < Timer : : getStringMemory ( _timer . getIncrease ( ) ) < < " ]. " < < endl ;
UpdateSession : : close ( ) ;
cmess2 < < " - Segments destroyed : " < < countSegments < < endl
< < " - Contacts destroyed : " < < countContacts < < endl ;
}
void KnikEngine : : unroute ( Segment * segment , set < Segment * > & segmentsToUnroute , Contact * fromContact )
// **************************************************************************************************
{
bool deleteSource = false ;
bool deleteTarget = false ;
if ( ! dynamic_cast < Contact * > ( segment - > getSource ( ) ) )
throw Error ( " KnikEngine::unroute() : found a Segment not based on a Contact . " ) ;
Contact * sourceContact = static_cast < Contact * > ( segment - > getSource ( ) ) ;
if ( sourceContact ! = fromContact ) {
Hook * contactHook = sourceContact - > getBodyHook ( ) ;
Hook * tempHook = contactHook - > getNextHook ( ) ;
Segment * firstSeg = NULL ;
Segment * secondSeg = NULL ;
unsigned NbSeg = 0 ;
bool routingPadPresent = false ;
while ( tempHook ! = contactHook ) {
if ( dynamic_cast < Segment * > ( tempHook - > getComponent ( ) ) ) {
NbSeg + + ;
if ( NbSeg > 2 )
break ; // ca sert a rien de continuer on a au moins 3 elements
if ( ! firstSeg )
firstSeg = static_cast < Segment * > ( tempHook - > getComponent ( ) ) ;
else
secondSeg = static_cast < Segment * > ( tempHook - > getComponent ( ) ) ;
}
if ( dynamic_cast < RoutingPad * > ( tempHook - > getComponent ( ) ) ) {
routingPadPresent = true ;
break ;
}
tempHook = tempHook - > getNextHook ( ) ;
}
if ( ! routingPadPresent & & ( NbSeg = = 2 ) ) { // on doit "unroute" l'autre segment aussi
if ( firstSeg = = segment )
unroute ( secondSeg , segmentsToUnroute , sourceContact ) ;
else if ( secondSeg = = segment )
unroute ( firstSeg , segmentsToUnroute , sourceContact ) ;
else
throw Error ( " KnikEngine::unroute() : Wow how did I do that ! " ) ;
deleteSource = true ;
}
}
if ( ! dynamic_cast < Contact * > ( segment - > getTarget ( ) ) )
throw Error ( " KnikEngine::unroute() : found a Segment not based on a Contact . " ) ;
Contact * targetContact = static_cast < Contact * > ( segment - > getTarget ( ) ) ;
if ( targetContact ! = fromContact ) {
Hook * contactHook = targetContact - > getBodyHook ( ) ;
Hook * tempHook = contactHook - > getNextHook ( ) ;
Segment * firstSeg = NULL ;
Segment * secondSeg = NULL ;
unsigned NbSeg = 0 ;
bool routingPadPresent = false ;
while ( tempHook ! = contactHook ) {
if ( Segment * seg = dynamic_cast < Segment * > ( tempHook - > getComponent ( ) ) ) {
NbSeg + + ;
if ( NbSeg > 2 )
break ; // ca sert a rien de continuer on a au moins 3 <20> l<EFBFBD> ments
if ( ! firstSeg )
firstSeg = seg ;
else
secondSeg = seg ;
}
if ( dynamic_cast < RoutingPad * > ( tempHook - > getComponent ( ) ) ) {
routingPadPresent = true ;
break ;
}
tempHook = tempHook - > getNextHook ( ) ;
}
if ( ! routingPadPresent & & ( NbSeg = = 2 ) ) { // on doit "unroute" l'autre segment aussi
if ( firstSeg = = segment )
unroute ( secondSeg , segmentsToUnroute , targetContact ) ;
else if ( secondSeg = = segment )
unroute ( firstSeg , segmentsToUnroute , targetContact ) ;
else
throw Error ( " KnikEngine::unroute() : Once again , how did I do that ! " ) ;
deleteTarget = true ;
}
}
segmentsToUnroute . erase ( segment ) ;
_routingGraph - > removeSegment ( segment ) ; // il faut mettre a jour les occupations des edges dans le graph !
segment - > getSourceHook ( ) - > detach ( ) ;
segment - > getTargetHook ( ) - > detach ( ) ;
segment - > destroy ( ) ;
if ( deleteSource )
sourceContact - > destroy ( ) ;
if ( deleteTarget )
targetContact - > destroy ( ) ;
}
void KnikEngine : : computeOverflow ( )
// *******************************
{
cmess1 < < " o Computing Statistics " < < endl ;
Vertex * currentVertex = _routingGraph - > getLowerLeftVertex ( ) ;
int nbEdgesTotal = 0 ;
int nbEdgesOver = 0 ;
unsigned overflow = 0 ;
unsigned maxOver = 0 ;
//float maxOver = 0;
//float averageOver = 0;
while ( currentVertex ) {
Vertex * firstLineVertex = currentVertex ;
while ( currentVertex ) {
Edge * hEdgeOut = currentVertex - > getHEdgeOut ( ) ;
if ( hEdgeOut ) {
nbEdgesTotal + + ;
int ov = 2 * ( hEdgeOut - > getRealOccupancy ( ) - hEdgeOut - > getCapacity ( ) ) ; // 2 = minimum spacing + minimum width
if ( ov > 0 ) {
nbEdgesOver + + ;
overflow + = ov ;
maxOver = ( unsigned ) ov > maxOver ? ov : maxOver ;
}
for_each_segment ( segment , hEdgeOut - > getSegments ( ) ) {
map < Segment * , SegRecord > : : iterator ssit = _segmentOverEdges . find ( segment ) ;
SegRecord record ;
if ( ssit ! = _segmentOverEdges . end ( ) )
record = ( * ssit ) . second ;
else
record = SegRecord ( ) ;
record . incNbTotEdges ( ) ;
if ( ov > 0 ) {
record . incNbOvEdges ( ) ;
record . incSumOv ( ov ) ;
record . UpdateMaxOv ( ov ) ;
}
end_for ;
}
}
if ( Edge * vEdgeOut = currentVertex - > getVEdgeOut ( ) ) {
nbEdgesTotal + + ;
int ov = 2 * ( vEdgeOut - > getRealOccupancy ( ) - vEdgeOut - > getCapacity ( ) ) ;
if ( ov > 0 ) {
nbEdgesOver + + ;
overflow + = ov ;
maxOver = ( unsigned ) ov > maxOver ? ov : maxOver ;
}
for_each_segment ( segment , vEdgeOut - > getSegments ( ) ) {
map < Segment * , SegRecord > : : iterator ssit = _segmentOverEdges . find ( segment ) ;
SegRecord record ;
if ( ssit ! = _segmentOverEdges . end ( ) )
record = ( * ssit ) . second ;
else
record = SegRecord ( ) ;
record . incNbTotEdges ( ) ;
if ( ov > 0 ) {
record . incNbOvEdges ( ) ;
record . incSumOv ( ov ) ;
record . UpdateMaxOv ( ov ) ;
}
end_for ;
}
}
if ( hEdgeOut )
currentVertex = hEdgeOut - > getOpposite ( currentVertex ) ;
else
break ;
}
Edge * vEdgeOut = firstLineVertex - > getVEdgeOut ( ) ;
if ( vEdgeOut )
currentVertex = vEdgeOut - > getOpposite ( firstLineVertex ) ;
else
break ;
}
cmess2 < < " - first skimming through edges done (overflow computed) " < < endl ;
//averageOver = nbEdgesOver == 0 ? 0 : averageOver / (float)nbEdgesOver;
// Now we've got the max we can print more detailed statistics about edges overflow
// except if there is no overflow...
vector < unsigned > ovEdgesStats ;
if ( maxOver ) {
Vertex * currentVertex = _routingGraph - > getLowerLeftVertex ( ) ;
unsigned maxOvIdx = maxOver / ( int ) ( 10 ) ;
ovEdgesStats . resize ( maxOvIdx + 1 ) ;
while ( currentVertex ) {
Vertex * firstLineVertex = currentVertex ;
while ( currentVertex ) {
Edge * hEdgeOut = currentVertex - > getHEdgeOut ( ) ;
if ( hEdgeOut ) {
int ov = 2 * ( hEdgeOut - > getRealOccupancy ( ) - hEdgeOut - > getCapacity ( ) ) ; // 2 = minimum sapcing + minimum width
if ( ov > 0 ) {
unsigned ovIdx = ov / int ( 10 ) ;
ovEdgesStats [ ovIdx ] + + ;
}
}
if ( Edge * vEdgeOut = currentVertex - > getVEdgeOut ( ) ) {
int ov = 2 * ( vEdgeOut - > getRealOccupancy ( ) - vEdgeOut - > getCapacity ( ) ) ;
if ( ov > 0 ) {
unsigned ovIdx = ov / int ( 10 ) ;
ovEdgesStats [ ovIdx ] + + ;
}
}
if ( hEdgeOut )
currentVertex = hEdgeOut - > getOpposite ( currentVertex ) ;
else
break ;
}
Edge * vEdgeOut = firstLineVertex - > getVEdgeOut ( ) ;
if ( vEdgeOut )
currentVertex = vEdgeOut - > getOpposite ( firstLineVertex ) ;
else
break ;
}
cmess2 < < " - second skimming through edges done (overflow details) " < < endl ;
}
unsigned _wirelength = 0 ;
unsigned _gridWirelength = 0 ;
unsigned _gridWirelengthWoVia = 0 ;
Layer * layerContact = DataBase : : getDB ( ) - > getTechnology ( ) - > getLayer ( Name ( " GCONTACT " ) ) ;
//for ( unsigned i = 0 ; i < _nets_to_route.size() ; i++ ) {
// Net* net = _nets_to_route[i]._net;
forEach ( Net * , net , _cell - > getNets ( ) ) {
unsigned netWirelength = 0 ;
for_each_segment ( segment , net - > getSegments ( ) ) {
_wirelength + = ( unsigned ) DbU : : getLambda ( segment - > getLength ( ) ) ;
unsigned gridWirelength = _routingGraph - > getGridLength ( segment ) ;
_gridWirelength + = gridWirelength ;
_gridWirelengthWoVia + = gridWirelength ;
netWirelength + = gridWirelength ;
end_for ;
}
for_each_contact ( contact , net - > getContacts ( ) ) {
if ( contact - > getLayer ( ) = = layerContact ) {
_gridWirelength + = 3 ;
netWirelength + = 3 ;
}
end_for ;
}
NetExtension : : setWireLength ( * net , netWirelength ) ;
}
cmess2 < < " - Wirelength computed " < < endl ;
// *** Cannot build column several times, no hasColumn function ***
// CEditor* editor = getCEditor ( getCell() );
// CNetListWindow* netListWindow = editor->getNetListWindow();
// if ( ! netListWindow->hasColumn ( "GridWirelength" ) ) {
// netListWindow->addColumn ( "GridWirelength", getNetWirelength, NetExtension::compare, CListWidget::RightJustify );
// netListWindow->Rebuild();
// }
// cmess2 << " - Netlist window rebuild" << endl;
// cmess1 << " - Total number of edges : " << nbEdgesTotal << endl
cmess1 < < " - Number of overcapacity edges : " < < nbEdgesOver < < " / " < < nbEdgesTotal < < endl
//<< " - Total calls to Dijkstra : " << countDijkstra << endl
//<< " - Total calls to Monotonic : " << countMonotonic << endl
//<< " - Total calls to Materialize : " << countMaterialize << endl
//<< " - Taille du Graphe de routage : " << _xSize << " x " << _ySize << endl
< < " - # of overflow : " < < overflow < < endl
< < " - max of overflow : " < < maxOver < < endl ;
// << " - # of net with overflow : " << _netNbOverEdges.size() << endl
cmess1 < < " - grid wirelength : " < < _gridWirelength < < endl ;
cmess2 < < " - grid wirelength : " < < _gridWirelength < < endl
< < " - grid wirelength w/o via : " < < _gridWirelengthWoVia < < endl
< < " - real wirelength : " < < _wirelength < < endl ;
//if ( ! ovEdgesStats.empty() ) {
// // print details about edges overflow
// cmess2 << endl
// << " - Number of edges for overflow interval :" << endl;
// for ( unsigned i = 0 ; i < ovEdgesStats.size() ; i++ ) {
// unsigned first = i*10;
// unsigned second = (i+1)*10 > maxOver ? maxOver : (i+1)*10;
// cmess2 << " - " << first << " - " << second << " : " << ovEdgesStats[i] << endl;
// }
//}
return ;
}
// void KnikEngine::showOccupancy()
// // *****************************
// {
// if ( _routingGraph )
// _routingGraph->UpdateOccupancyWindow();
// }
void KnikEngine : : run ( )
// *******************
{
Route ( ) ;
bool done = analyseRouting ( ) ;
while ( ! done ) {
unrouteOvSegments ( ) ;
reroute ( ) ;
done = analyseRouting ( ) ;
}
2010-04-23 08:13:22 -05:00
addMeasure < double > ( getCell ( ) , " knikT " , _timer . getCombTime ( ) ) ;
addMeasure < size_t > ( getCell ( ) , " knikS " , ( _timer . getMemorySize ( ) > > 20 ) ) ;
2010-05-13 04:45:53 -05:00
computeSymbolicWireLength ( ) ;
2010-03-09 09:23:58 -06:00
}
void KnikEngine : : Route ( )
// *********************
{
UpdateSession : : open ( ) ;
if ( ! __initialized__ )
initGlobalRouting ( ) ;
_timer . resetIncrease ( ) ;
_timer . start ( ) ;
cmess1 < < " o Knik::Route() " < < endl ;
//CEditor* editor = getCEditor ( getCell() );
//editor->showRubbers();
//editor->Refresh();
//editor->Stop("Global Routing is going to do its job");
// initializing netStamp for routingGraph:
//_routingGraph->setNetStamp(1); // Maybe NetStamp should not be initialized here !
// Be aware that initializingthe NetStamp in the construction of the routingGraph, might be a bad idea, if a lotof rerouting processes are run, it may overpass the unsigne limit (really ?)
Name nameDebug ( " ck_dpt " ) ;
unsigned size = _nets_to_route . size ( ) ;
for ( unsigned i = 0 ; i < size ; i + + ) {
Net * net = _nets_to_route [ i ] . _net ;
assert ( net ) ;
2010-11-16 07:59:03 -06:00
2010-03-09 09:23:58 -06:00
//_routingGraph->checkGraphConsistency();
switch ( _routingGraph - > initRouting ( net ) ) {
case 0 :
case 1 :
//cerr << "Nothing to global route" << endl;
break ;
case 2 :
//_routingGraph->Monotonic();
//break;
default :
_routingGraph - > Dijkstra ( ) ;
break ;
}
_routingGraph - > incNetStamp ( ) ;
_routingGraph - > CleanRoutingState ( ) ;
//cmess1 << " - [";
//cmess1.width(3);
//cmess1 << floor((float)(i*100)/(float)(size));
//cmess1 << "%]\r";
}
_timer . suspend ( ) ;
cmess1 < < " - [100%]: " < < size < < " nets routed. " < < endl ;
//cmess2 << " - NbSplitters : " << _routingGraph->getNbSplitters() << endl;
cmess2 < < " + Done in " < < _timer . getCombTime ( )
< < " s [+ " < < Timer : : getStringMemory ( _timer . getIncrease ( ) ) < < " ]. " < < endl ;
cmess2 < < " (raw measurements : " < < _timer . getCombTime ( )
< < " s [+ " < < ( _timer . getIncrease ( ) > > 10 ) < < " Ko/ "
< < ( _timer . getMemorySize ( ) > > 10 ) < < " Ko]) " < < endl ;
// Comment to test with transhierarchic MIPS
//computeOverflow();
// To be able to plot congestionMap, we need to UpdateMaxEstimateCongestion :
//_routingGraph->UpdateMaxEstimateCongestion(); // no more useful since qe use QT which allow to see colored edges.
// passage en mode PERFORMANCE !
//_routingGraph->testSTuplePQ();
// While not debugging, comment this out :
//_routingGraph->destroy();
UpdateSession : : close ( ) ;
_routingDone = true ;
}
bool KnikEngine : : analyseRouting ( )
// ******************************
{
//computeOverflow();
if ( _routingDone )
_timer . resume ( ) ;
else {
_timer . resetIncrease ( ) ;
_timer . start ( ) ;
}
unsigned overflow = _routingGraph - > analyseRouting ( _segmentsToUnroute ) ;
cmess2 < < " - Segments to unroute : " < < _segmentsToUnroute . size ( ) < < endl ;
// redefine the new _nets_to_route vector
_nets_to_route . clear ( ) ;
for ( set < Segment * > : : iterator it = _segmentsToUnroute . begin ( ) ; it ! = _segmentsToUnroute . end ( ) ; it + + ) {
cmess2 < < " " < < ( * it ) < < endl ;
Net * net = ( * it ) - > getNet ( ) ;
bool present = false ;
for ( unsigned i = 0 ; i < _nets_to_route . size ( ) ; i + + ) {
if ( _nets_to_route [ i ] . _net = = net ) {
present = true ;
break ;
}
}
if ( ! present ) {
Box bbox = net - > getBoundingBox ( ) ;
NetRecord record ( net , ( long int ) ( ( DbU : : getLambda ( bbox . getWidth ( ) ) + 1 ) * ( DbU : : getLambda ( bbox . getHeight ( ) ) + 1 ) ) ) ;
_nets_to_route . push_back ( record ) ;
}
}
// Il est nécessaire de retrier les nets à rerouter de façon uqe le Dijkstra soit optimisé
stable_sort ( _nets_to_route . begin ( ) , _nets_to_route . end ( ) , NetSurfacesComp ( ) ) ;
NetVector : : iterator new_end = unique ( _nets_to_route . begin ( ) , _nets_to_route . end ( ) ) ;
_nets_to_route . erase ( new_end , _nets_to_route . end ( ) ) ;
//cmess1 << " - Nets to reroute : " << _nets_to_route.size() << endl;
//cmess1 << " ";
//for ( unsigned i = 0 ; i < _nets_to_route.size() ; i++ )
// cmess1 << _nets_to_route[i]._net->getName() << "|";
//cmess1 << endl;
_timer . suspend ( ) ;
cmess1 < < " + Done in " < < _timer . getCombTime ( )
< < " s [+ " < < Timer : : getStringMemory ( _timer . getIncrease ( ) ) < < " ]. " < < endl ;
bool done = false ;
if ( ( overflow = = 0 ) | | ( _timer . getCombTime ( ) > = MAX_RUNTIME ) | | ( _rerouteIteration > = MAX_ITERATION ) )
done = true ;
return done ;
}
void KnikEngine : : reroute ( )
// ***********************
{
UpdateSession : : open ( ) ;
//Breakpoint::setStopLevel(1);
//analyseRouting();
//unrouteOvSegments();
cmess1 < < " o Knik::reroute() : iteration " < < + + _rerouteIteration < < endl ;
_timer . resume ( ) ;
unsigned size = _nets_to_route . size ( ) ;
__ripupMode__ = true ;
for ( unsigned i = 0 ; i < size ; i + + ) {
Net * net = _nets_to_route [ i ] . _net ;
assert ( net ) ;
//_routingGraph->checkGraphConsistency();
switch ( _routingGraph - > initRouting ( net ) ) {
case 0 :
case 1 :
//cerr << "Nothing to global route" << endl;
break ;
default :
_routingGraph - > Dijkstra ( ) ;
break ;
}
_routingGraph - > incNetStamp ( ) ;
_routingGraph - > CleanRoutingState ( ) ;
//cmess1 << " - [";
//cmess1.width(3);
//cmess1 << floor((float)(i*100)/(float)(size));
//cmess1 << "%]\r";
}
_timer . suspend ( ) ;
cmess1 < < " - [100%]: " < < size < < " nets routed. " < < endl ;
//cmess2 << " - NbSplitters : " << _routingGraph->getNbSplitters() << endl;
cmess2 < < " + Done in " < < _timer . getCombTime ( )
< < " [+ " < < Timer : : getStringMemory ( _timer . getIncrease ( ) ) < < " ]. " < < endl ;
cmess2 < < " (raw measurements : " < < _timer . getCombTime ( )
< < " s [+ " < < ( _timer . getIncrease ( ) > > 10 ) < < " Ko/ "
< < ( _timer . getMemorySize ( ) > > 10 ) < < " Ko]) " < < endl ;
// Comment to test with transhierarchic MIPS
//computeOverflow();
// While not debugging, comment this out :
//_routingGraph->destroy();
UpdateSession : : close ( ) ;
}
2010-05-13 04:45:53 -05:00
void KnikEngine : : computeSymbolicWireLength ( )
{
// Ugly: hardcoded SxLib gauge characteristics.
2010-08-22 07:37:08 -05:00
size_t hEdgeCapacity = 0 ;
size_t vEdgeCapacity = 0 ;
double gcellSide = 50.0 ;
RoutingGauge * rg = AllianceFramework : : get ( ) - > getRoutingGauge ( ) ;
vector < RoutingLayerGauge * > : : const_iterator ilayerGauge = rg - > getLayerGauges ( ) . begin ( ) ;
for ( ; ilayerGauge ! = rg - > getLayerGauges ( ) . end ( ) ; + + ilayerGauge ) {
RoutingLayerGauge * layerGauge = ( * ilayerGauge ) ;
if ( layerGauge - > getType ( ) ! = Constant : : Default ) continue ;
if ( layerGauge - > getDirection ( ) = = Constant : : Horizontal ) {
hEdgeCapacity + = layerGauge - > getTrackNumber ( 0 , DbU : : lambda ( 50.0 ) ) - 1 ;
} else if ( layerGauge - > getDirection ( ) = = Constant : : Vertical ) {
vEdgeCapacity + = layerGauge - > getTrackNumber ( 0 , DbU : : lambda ( 50.0 ) ) - 1 ;
}
}
// Complete formula: unitarian Wirelength/Area for one GCell.
// (side*(hEdgeCapacity+vEdgeCapacity)) / (side * side).
const double normalize = ( ( double ) ( hEdgeCapacity + vEdgeCapacity ) ) / gcellSide ;
2010-05-13 04:45:53 -05:00
unsigned long long symbolicWireLength = 0 ;
forEach ( Net * , net , getCell ( ) - > getNets ( ) ) {
if ( net - > isGlobal ( )
or net - > isSupply ( )
2010-08-22 07:37:08 -05:00
or net - > isClock ( ) ) {
2010-05-13 04:45:53 -05:00
continue ;
}
forEach ( Segment * , isegment , net - > getSegments ( ) ) {
symbolicWireLength + = ( unsigned long long ) DbU : : getLambda ( isegment - > getLength ( ) ) ;
}
}
addMeasure < unsigned long long > ( getCell ( ) , " GWL(l) " , symbolicWireLength , 14 ) ;
Box ab ( getCell ( ) - > getAbutmentBox ( ) ) ;
double area = ( DbU : : getLambda ( ab . getWidth ( ) ) * DbU : : getLambda ( ab . getHeight ( ) ) ) ;
addMeasure < double > ( getCell ( ) , " Area(l2) " , area , 14 ) ;
addMeasure < double > ( getCell ( ) , " Sat. " , ( symbolicWireLength / area ) / normalize ) ;
}
2010-03-09 09:23:58 -06:00
Record * KnikEngine : : _getRecord ( ) const
// *****************************
{
Record * record = Inherit : : _getRecord ( ) ;
if ( ! record )
record = new Record ( getString ( this ) ) ;
record - > add ( getSlot ( " RoutingGraph " , _routingGraph ) ) ;
return record ;
}
KnikEngine * KnikEngine : : get ( const Cell * cell )
// ********************************************
{
return ( dynamic_cast < KnikEngine * > ( ToolEngine : : get ( cell , KnikEngine : : staticGetName ( ) ) ) ) ;
}
} // namespace Knik
// *********************************************************************
// Copyright (C) UPMC/LIP6/ASIM 2003-2004 All rights reserved
// *********************************************************************