397 lines
12 KiB
C++
397 lines
12 KiB
C++
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC 2019-2010, All Rights Reserved
|
|
//
|
|
// +-----------------------------------------------------------------+
|
|
// | C O R I O L I S |
|
|
// | K i t e - D e t a i l e d R o u t e r |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./BloatProfile.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
#include <map>
|
|
#include <list>
|
|
#include "hurricane/DebugSession.h"
|
|
#include "hurricane/Error.h"
|
|
#include "hurricane/Warning.h"
|
|
#include "hurricane/DataBase.h"
|
|
#include "hurricane/Technology.h"
|
|
#include "hurricane/BasicLayer.h"
|
|
#include "hurricane/RegularLayer.h"
|
|
#include "hurricane/NetExternalComponents.h"
|
|
#include "hurricane/NetRoutingProperty.h"
|
|
#include "hurricane/Instance.h"
|
|
#include "hurricane/Plug.h"
|
|
#include "hurricane/Path.h"
|
|
#include "hurricane/Query.h"
|
|
#include "crlcore/Utilities.h"
|
|
#include "crlcore/AllianceFramework.h"
|
|
#include "anabatic/GCell.h"
|
|
#include "etesian/BloatProperty.h"
|
|
#include "katana/KatanaEngine.h"
|
|
|
|
|
|
namespace {
|
|
|
|
using namespace std;
|
|
using Hurricane::Error;
|
|
using Hurricane::Warning;
|
|
using Hurricane::DbU;
|
|
using Hurricane::Entity;
|
|
using Hurricane::Instance;
|
|
using Hurricane::Path;
|
|
using Hurricane::Transformation;
|
|
using Hurricane::Occurrence;
|
|
using Etesian::BloatState;
|
|
using Etesian::BloatExtension;
|
|
using Anabatic::Edge;
|
|
using namespace Katana;
|
|
|
|
class Slices;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "FlatInstance".
|
|
|
|
class FlatInstance {
|
|
public:
|
|
static DbU::Unit getXFromOccurrence ( Occurrence );
|
|
static DbU::Unit getYFromOccurrence ( Occurrence );
|
|
public:
|
|
inline FlatInstance ( Occurrence );
|
|
inline DbU::Unit getX () const;
|
|
inline Occurrence getOccurrence () const;
|
|
private:
|
|
DbU::Unit _x;
|
|
Occurrence _instanceOcc;
|
|
};
|
|
|
|
|
|
DbU::Unit FlatInstance::getXFromOccurrence ( Occurrence o )
|
|
{
|
|
Instance* instance = dynamic_cast<Instance*>( o.getEntity() );
|
|
Transformation transf = instance->getTransformation();
|
|
o.getPath().getTransformation().applyOn( transf );
|
|
Box ab = instance->getMasterCell()->getAbutmentBox();
|
|
transf.applyOn( ab );
|
|
return ab.getXMin();
|
|
}
|
|
|
|
|
|
DbU::Unit FlatInstance::getYFromOccurrence ( Occurrence o )
|
|
{
|
|
Instance* instance = dynamic_cast<Instance*>( o.getEntity() );
|
|
Transformation transf = instance->getTransformation();
|
|
|
|
//cerr << "Inst transf:" << transf << endl;
|
|
//cerr << "Path transf:" << o.getPath().getTransformation() << endl;
|
|
|
|
o.getPath().getTransformation().applyOn( transf );
|
|
Box ab = instance->getMasterCell()->getAbutmentBox();
|
|
transf.applyOn( ab );
|
|
return ab.getYMin();
|
|
}
|
|
|
|
|
|
|
|
inline FlatInstance::FlatInstance ( Occurrence o )
|
|
: _x(getXFromOccurrence(o))
|
|
, _instanceOcc(o)
|
|
{ }
|
|
|
|
|
|
inline DbU::Unit FlatInstance::getX () const { return _x; }
|
|
inline Occurrence FlatInstance::getOccurrence () const { return _instanceOcc; }
|
|
|
|
|
|
bool operator< ( const FlatInstance& lhs, const FlatInstance& rhs )
|
|
{ return lhs.getX() < rhs.getX(); }
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Slice".
|
|
|
|
class Slice {
|
|
public:
|
|
inline Slice ( Slices*, GCell* );
|
|
inline bool useStaticBloatProfile () const;
|
|
inline uint32_t getBloatOverloadAdd () const;
|
|
inline DbU::Unit getY () const;
|
|
inline void add ( Occurrence );
|
|
inline void sort ();
|
|
void tagOverloadeds ( size_t& count, size_t& newCount );
|
|
private:
|
|
Slices* _owner;
|
|
GCell* _left;
|
|
vector<FlatInstance> _instances;
|
|
};
|
|
|
|
|
|
inline Slice::Slice ( Slices* owner, GCell* left )
|
|
: _owner (owner)
|
|
, _left (left)
|
|
, _instances()
|
|
{ }
|
|
|
|
|
|
inline DbU::Unit Slice::getY () const { return _left->getYMin(); }
|
|
inline void Slice::add ( Occurrence o ) { _instances.push_back( o ); }
|
|
inline void Slice::sort () { std::sort( _instances.begin(), _instances.end() ); }
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Slices".
|
|
|
|
class Slices {
|
|
public:
|
|
Slices ( KatanaEngine* );
|
|
~Slices ();
|
|
inline KatanaEngine* getKatana () const;
|
|
inline void add ( Occurrence );
|
|
inline void sort ();
|
|
inline void tagOverloadeds ();
|
|
private:
|
|
KatanaEngine* _katana;
|
|
Box _cellAb;
|
|
DbU::Unit _sliceHeight;
|
|
vector<Slice*> _slices;
|
|
};
|
|
|
|
|
|
Slices::Slices ( KatanaEngine* katana )
|
|
: _katana (katana)
|
|
, _cellAb (_katana->getCell()->getAbutmentBox())
|
|
, _sliceHeight(_katana->getConfiguration()->getSliceHeight())
|
|
, _slices ()
|
|
{
|
|
GCell* left = _katana->getSouthWestGCell();
|
|
size_t slicesNb = _cellAb.getHeight() / _sliceHeight;
|
|
|
|
for ( size_t islice=0 ; islice<slicesNb ; ++islice ) {
|
|
if (not left)
|
|
throw Error( "Slices::Slices(): No GCell under slice [%d] @%s in \"%s\"."
|
|
, islice, DbU::getValueString( (DbU::Unit)islice * _sliceHeight).c_str()
|
|
, getString(_katana->getCell()->getName()).c_str()
|
|
);
|
|
|
|
if (not left->isMatrix())
|
|
throw Error( "Slices::Slices(): Non-matrix GCell under slice [%d] @%s in \"%s\".\n"
|
|
" (%s)"
|
|
, islice, DbU::getValueString( (DbU::Unit)islice * _sliceHeight).c_str()
|
|
, getString(_katana->getCell()->getName()).c_str()
|
|
, getString(left).c_str()
|
|
);
|
|
|
|
if (left->getYMin() != (DbU::Unit)islice * _sliceHeight + _cellAb.getYMin())
|
|
throw Error( "Slices::Slices(): Misaligned GCell under slice [%d] @%s in \"%s\".\n"
|
|
" (%s)"
|
|
, islice, DbU::getValueString( (DbU::Unit)islice * _sliceHeight).c_str()
|
|
, getString(_katana->getCell()->getName()).c_str()
|
|
, getString(left).c_str()
|
|
);
|
|
|
|
_slices.push_back( new Slice( this, left ) );
|
|
left = left->getNorth();
|
|
}
|
|
}
|
|
|
|
|
|
Slices::~Slices ()
|
|
{ for ( Slice* slice : _slices ) delete slice; }
|
|
|
|
|
|
inline KatanaEngine* Slices::getKatana () const
|
|
{ return _katana; }
|
|
|
|
|
|
inline void Slices::sort ()
|
|
{ for ( Slice* slice : _slices ) slice->sort(); }
|
|
|
|
|
|
inline void Slices::add ( Occurrence o )
|
|
{
|
|
DbU::Unit y = FlatInstance::getYFromOccurrence( o );
|
|
size_t islice = (y - _cellAb.getYMin()) / _sliceHeight;
|
|
|
|
if (islice >= _slices.size()) {
|
|
throw Error( "Slices::add(): Out of range instance occurrence placed at Y %s (slice:%u).\n"
|
|
" (%s)"
|
|
, DbU::getValueString(y).c_str()
|
|
, islice
|
|
, o.getCompactString().c_str()
|
|
);
|
|
}
|
|
|
|
_slices[islice]->add( o );
|
|
}
|
|
|
|
|
|
inline void Slices::tagOverloadeds ()
|
|
{
|
|
size_t count = 0;
|
|
size_t newCount = 0;
|
|
for ( Slice* slice : _slices ) slice->tagOverloadeds( count, newCount );
|
|
|
|
cmess2 << Dots::asUInt (" - Bloated cells" ,count ) << endl;
|
|
cmess2 << Dots::asUInt (" - Bloated cells, new" ,newCount) << endl;
|
|
}
|
|
|
|
|
|
inline bool Slice::useStaticBloatProfile () const
|
|
{ return _owner->getKatana()->useStaticBloatProfile(); }
|
|
|
|
|
|
inline uint32_t Slice::getBloatOverloadAdd () const
|
|
{ return _owner->getKatana()->getBloatOverloadAdd(); }
|
|
|
|
|
|
void Slice::tagOverloadeds ( size_t& count, size_t& newCount )
|
|
{
|
|
GCell* gcell = _left;
|
|
size_t iLeft = 0;
|
|
size_t iRight = 0;
|
|
|
|
while ( gcell ) {
|
|
//cerr << "> Under:" << gcell << endl;
|
|
|
|
uint32_t overload = 0;
|
|
for ( Edge* edge : gcell->getEdges( Flags::NorthSide|Flags::EastSide ) ) {
|
|
if (edge->getRealOccupancy() > edge->getCapacity()) {
|
|
overload = std::max( overload, edge->getRealOccupancy() - edge->getCapacity() );
|
|
|
|
// if (edge->getRealOccupancy() > edge->getRawCapacity()) {
|
|
// overload += 4;
|
|
// }
|
|
}
|
|
}
|
|
|
|
iLeft = iRight;
|
|
while ( iRight < _instances.size() ) {
|
|
if (_instances[iRight].getX() >= gcell->getXMax()) break;
|
|
++iRight;
|
|
}
|
|
|
|
if (iLeft >= _instances.size()) break;
|
|
|
|
if (overload) {
|
|
overload += getBloatOverloadAdd();
|
|
|
|
for ( size_t i=iLeft ; i<iRight ; ++i ) {
|
|
BloatState* state = BloatExtension::get( _instances[i].getOccurrence() );
|
|
if (not state) {
|
|
if ( (_owner->getKatana()->getPassNumber() > 0) and useStaticBloatProfile() )
|
|
continue;
|
|
|
|
state = BloatExtension::create( _instances[i].getOccurrence(), overload );
|
|
++newCount;
|
|
|
|
//cerr << "| Bloat: " << overload << " " << _instances[i].getOccurrence() << endl;
|
|
} else {
|
|
state->setTracksCount( state->getTracksCount() + overload );
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
|
|
gcell = gcell->getEast();
|
|
}
|
|
|
|
|
|
// GCell* gcell = _left;
|
|
// Edge* eastEdge = _left->getEastEdge();
|
|
// Edge* northEdge = _left->getNorthEdge();
|
|
// bool bloated = false;
|
|
|
|
// //cerr << "+ Slice @" << DbU::getValueString(getY()) << endl;
|
|
|
|
// for ( FlatInstance& fi : _instances ) {
|
|
// //cerr << "| @" << DbU::getValueString(fi.getX()) << " " << fi.getOccurrence() << endl;
|
|
|
|
// if (fi.getX() >= gcell->getXMax()) {
|
|
// for ( gcell = gcell->getEast() ; gcell and (fi.getX() > gcell->getXMax())
|
|
// ; gcell = gcell->getEast() ) {
|
|
// //cerr << "| Skip " << gcell << endl;
|
|
// }
|
|
// //cerr << "| Advance to " << gcell << endl;
|
|
// if (not gcell) break;
|
|
|
|
// bloated = false;
|
|
// eastEdge = gcell->getEastEdge();
|
|
// northEdge = gcell->getNorthEdge();
|
|
// }
|
|
|
|
// unsigned int overload = 0;
|
|
|
|
// if (eastEdge) {
|
|
// if (eastEdge->getRealOccupancy() > eastEdge->getCapacity()) {
|
|
// overload = eastEdge->getRealOccupancy() - eastEdge->getCapacity();
|
|
// }
|
|
// // else if (eastEdge->getHistoricCost() > 3.0) {
|
|
// // overload = 4;
|
|
// // }
|
|
// }
|
|
|
|
// if (northEdge) {
|
|
// if (northEdge->getRealOccupancy() > northEdge->getCapacity()) {
|
|
// overload = std::max( overload, northEdge->getRealOccupancy() - northEdge->getCapacity() );
|
|
// }
|
|
// // else if (northEdge->getHistoricCost() > 3.0) {
|
|
// // overload = 4;
|
|
// // }
|
|
// }
|
|
|
|
// if (overload and not bloated) {
|
|
// bloated = true;
|
|
// overload += 8;
|
|
|
|
// BloatState* state = BloatExtension::get( fi.getOccurrence() );
|
|
// if (not state) {
|
|
// state = BloatExtension::create( fi.getOccurrence(), overload );
|
|
// //cerr << "> Bloat: " << fi.getOccurrence() << endl;
|
|
// //cerr << "> Under:" << gcell << endl;
|
|
// ++newCount;
|
|
// } else {
|
|
// state->setTracksCount( state->getTracksCount() + overload );
|
|
// }
|
|
// ++count;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
|
|
} // Anonymous namespace.
|
|
|
|
|
|
namespace Katana {
|
|
|
|
using CRL::CatalogExtension;
|
|
|
|
|
|
void KatanaEngine::_buildBloatProfile ()
|
|
{
|
|
cmess1 << " o Build bloat profile on \"" << getCell()->getName() << "\"." << endl;
|
|
|
|
Slices slices ( this );
|
|
|
|
for ( Occurrence occurrence : getCell()->getLeafInstanceOccurrences() )
|
|
{
|
|
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
|
|
Cell* masterCell = instance->getMasterCell();
|
|
|
|
if (CatalogExtension::isFeed(masterCell)) continue;
|
|
|
|
slices.add( occurrence );
|
|
}
|
|
|
|
slices.sort();
|
|
slices.tagOverloadeds();
|
|
}
|
|
|
|
|
|
} // Katana namespace.
|