coriolis/kite/src/TrackElement.cpp

291 lines
10 KiB
C++
Raw Normal View History

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
2015-03-17 10:42:12 -05:00
// Copyright (c) UPMC 2008-2015, 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 : "./TrackElement.cpp" |
// +-----------------------------------------------------------------+
#include <limits>
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Warning.h"
#include "hurricane/Net.h"
#include "hurricane/Name.h"
#include "katabatic/AutoContact.h"
#include "katabatic/GCell.h"
#include "crlcore/RoutingGauge.h"
#include "kite/DataNegociate.h"
#include "kite/TrackElement.h"
#include "kite/TrackCost.h"
#include "kite/Track.h"
#include "kite/Session.h"
#include "kite/RoutingEvent.h"
#include "kite/NegociateWindow.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace CRL;
using namespace Kite;
void dummyOverlapCost ( const TrackElement* segment, TrackCost& cost )
{
cerr << Warning("No overlapCost callback has been set (%s)."
,getString(segment).c_str()) << endl;
}
} // Anonymous namespace.
namespace Kite {
using Hurricane::inltrace;
using Hurricane::ltracein;
using Hurricane::ltraceout;
using Hurricane::tab;
using Hurricane::Bug;
using Hurricane::Net;
using Hurricane::Name;
using Katabatic::GCell;
// -------------------------------------------------------------------
// Comparison Classes.
//
// Return: lhs < rhs.
bool Compare::operator() ( TrackElement* lhs, TrackElement* rhs )
{ return lhs->getFreedomDegree() > rhs->getFreedomDegree(); }
bool CompareByPosition::operator() ( const TrackElement* lhs, const TrackElement* rhs ) const
{
if (lhs == rhs) return false;
if (lhs->isBlockage() xor rhs->isBlockage()) return lhs->isBlockage();
if (lhs->getLength() < rhs->getLength()) return true;
if (lhs->getLength() > rhs->getLength()) return false;
if (lhs->isHorizontal() xor rhs->isHorizontal()) return rhs->isHorizontal();
if (lhs->getAxis() > rhs->getAxis()) return true;
if (lhs->getAxis() < rhs->getAxis()) return false;
if (lhs->getSourceU() > rhs->getSourceU()) return true;
if (lhs->getSourceU() < rhs->getSourceU()) return false;
if (lhs->isBlockage() and rhs->isBlockage()) return false;
return lhs->getId() < rhs->getId();
}
// -------------------------------------------------------------------
// Class : "SegmentObserver".
void SegmentObserver::notify ( unsigned int flags )
{
TrackElement* segment = getOwner();
if (flags & AutoSegment::Invalidate) {
if (not segment->isInvalidated()) {
ltrace(200) << "::notify() <Invalidate> on " << segment << endl;
segment->invalidate();
}
}
if (flags & AutoSegment::Revalidate) {
// Revalidation must be delayed until *all* the AutoSegments have been revalidated.
// if (segment->isInvalidated()) {
// ltrace(200) << "::notify() <Revalidate> on " << segment << endl;
// segment->revalidate( true );
// }
}
if (flags & AutoSegment::RevalidatePPitch) {
segment->updatePPitch();
}
}
// -------------------------------------------------------------------
// Class : "TrackElement".
SegmentOverlapCostCB* TrackElement::_overlapCostCallback = dummyOverlapCost;
SegmentOverlapCostCB* TrackElement::setOverlapCostCB ( SegmentOverlapCostCB* cb )
{
SegmentOverlapCostCB* oldCb = _overlapCostCallback;
_overlapCostCallback = cb;
return oldCb;
}
// Wrapped AutoSegment Functions.
AutoSegment* TrackElement::base () const { return NULL; }
bool TrackElement::isFixed () const { return false; }
bool TrackElement::isLocal () const { return true; }
bool TrackElement::isGlobal () const { return not isLocal(); }
bool TrackElement::isBipoint () const { return false; }
bool TrackElement::isTerminal () const { return false; }
bool TrackElement::isStrongTerminal ( unsigned int ) const { return false; }
bool TrackElement::isStrap () const { return false; }
bool TrackElement::isSlackened () const { return false; }
bool TrackElement::isDogleg () const { return false; }
bool TrackElement::isSameLayerDogleg () const { return false; }
Implementation of pre-routing support (for clock-tree compliance). * New: In Katabatic, in <AutoContact>, this class is no longer derived from ExtentionGo. With the simplificated AutoContacts, there is no reason to do so, and it will save some QuadTree insertions/deletions. New factory function AutoContact::createFrom(Contact*) which try to build an AutoContact on top of a Hurricane::Contact. Of course that base contact *must fit* into one of the predefined Contact configurations (Terminal, Turn, HTee or VTee). NOTE: This implies that the pre-routed segments & contacts *are* correctly articulated, which is not the case when a Cell is read from disk in "ap" format. The pre-routing feature must be used for now without any re-read from disk. We will implement a re-articulating pre-process in the future. * Change: In Katabatic, in <AutoContact> derived classes, the ::updateCache() method now display an accurate error message if a segment is connected but has no AutoSegment conterpart (i.e. the lookup fails). * New: In Katabatic, in <AutoSegment>, the ::computeOptimal() method is short-circuited for pre-routed segments, the optimal axis position is considered to be the one it is currently on (i.e. we trust the designer). * New: In Katabatic, in <KatabaticEngine>, the ::loadGlobalRouting() method now accept a map of excluded nets (same as Knik). This map is the one of pre-routed nets. * New: In Katabatic, in layer assignment, do not try to displace fixed segments... * New: In Katabatic, in <AutoSegment>, new flag SegUserDefined and related methods to know if a segment comes from the global router (Knik) or is pre-routed (supplied by the user). * New: In Kite, In <BuildPowerRails>, support (exclusion) for pre-routed nets. * New: In Kite, In <GraphicKiteEngine> new menu entry for running the router on pre-routed nets ("Detailed Pre-Route"), also integrated in the all-on-one route command. * New: In Kite, In KiteEngine, new method ::_initDataBase() that group all the initialisation steps. It is a mix of calls between Knik and Kite initializations which are intertwinneds (may have to devellop a shared common base at a later point). It creates the Knik grid, then the Katabatic grid, then load pre-routed wires and power rails and protect isolated RoutingPads. Add support for a map of pre-routed nets (to be excluded for Knik calls). The method "::run()" now uses function flags, firstly to know if it is managing pre-routed wires or general purposes ones. * New: In Kite, in <NegociateWindow>, the "::run()" methods has now two modes. The normal one and the 'KtPreRoutedStage' that is for routing pre-routed nets. When in pre-route stage, the wires are fixed at the end of this step. * New: In Kite, in <TrackElement> add decorator for AutoSegment isUsedDefined(). * New: In Kite, in <TrackSegment>, the various ::canDogleg() methods returns false for a pre-routed (user-defined segment). * New: In Kite, in PyKiteEngine, added new method runNegociatePreRouted().
2014-06-21 13:16:47 -05:00
bool TrackElement::isUserDefined () const { return false; }
// Predicates.
bool TrackElement::canSlacken () const { return false; }
bool TrackElement::canPivotUp ( float ) const { return false; };
bool TrackElement::canPivotDown ( float ) const { return false; };
bool TrackElement::canMoveUp ( float, unsigned int ) const { return false; };
bool TrackElement::canDogleg () { return false; };
bool TrackElement::canDogleg ( Interval ) { return false; };
bool TrackElement::canDogleg ( Katabatic::GCell*, unsigned int ) { return false; };
// Accessors.
unsigned long TrackElement::getId () const { return 0; }
unsigned long TrackElement::getFreedomDegree () const { return 0; }
DbU::Unit TrackElement::getPitch () const { return 0; }
DbU::Unit TrackElement::getPPitch () const { return 0; }
float TrackElement::getMaxUnderDensity ( unsigned int ) const { return 0.0; };
unsigned int TrackElement::getDoglegLevel () const { return 0; }
TrackElement* TrackElement::getParent () const { return NULL; }
Interval TrackElement::getSourceConstraints () const { return Interval(); }
Interval TrackElement::getTargetConstraints () const { return Interval(); }
DataNegociate* TrackElement::getDataNegociate ( unsigned int ) const { return NULL; }
TrackElements TrackElement::getPerpandiculars () { return new TrackElements_Perpandiculars(NULL); }
void TrackElement::invalidate () { }
TrackElement* TrackElement::getCanonical ( Interval& i ) { i=Interval(getSourceU(),getTargetU()); return this; }
TrackElement* TrackElement::getSourceDogleg () { return NULL; }
TrackElement* TrackElement::getTargetDogleg () { return NULL; }
// Mutators.
void TrackElement::setTrack ( Track* track ) { _track = track; }
void TrackElement::updateFreedomDegree () { }
void TrackElement::setDoglegLevel ( unsigned int ) { }
void TrackElement::swapTrack ( TrackElement* ) { }
void TrackElement::reschedule ( unsigned int ) { }
void TrackElement::detach () { }
void TrackElement::revalidate () { }
void TrackElement::updatePPitch () { }
void TrackElement::setAxis ( DbU::Unit, unsigned int flags ) { }
TrackElement* TrackElement::makeDogleg () { return NULL; }
TrackElement* TrackElement::makeDogleg ( Interval, unsigned int& ) { return NULL; }
TrackElement* TrackElement::makeDogleg ( Katabatic::GCell*, TrackElement*&, TrackElement*& ) { return NULL; }
void TrackElement::_postDoglegs ( TrackElement*&, TrackElement*& ) { }
bool TrackElement::moveAside ( unsigned int ) { return false; }
bool TrackElement::slacken ( unsigned int ) { return false; }
bool TrackElement::moveUp ( unsigned int ) { return false; }
bool TrackElement::moveDown ( unsigned int ) { return false; }
#if THIS_IS_DISABLED
void TrackElement::desalignate () { }
#endif
bool TrackElement::_check () const { return true; }
TrackElement::TrackElement ( Track* track )
: _flags (0)
, _track (track)
, _index ((size_t)-1)
, _sourceU (0)
, _targetU (0)
, _observer(this)
{ }
void TrackElement::_postCreate ()
{ }
TrackElement::~TrackElement ()
{ }
void TrackElement::_preDestroy ()
{ }
void TrackElement::destroy ()
{
_preDestroy ();
delete this;
}
TrackElement* TrackElement::getNext () const
{
size_t dummy = _index;
return _track->getNext( dummy, getNet() );
}
TrackElement* TrackElement::getPrevious () const
{
size_t dummy = _index;
return _track->getPrevious( dummy, getNet() );
}
Interval TrackElement::getFreeInterval () const
{
if (not _track) return Interval(false);
size_t begin = _index;
size_t end = _index;
return _track->expandFreeInterval( begin, end, Track::InsideElement, getNet() );
}
size_t TrackElement::getGCells ( Katabatic::GCellVector& gcells ) const
{
vector<GCell*>().swap( gcells );
return gcells.size();
}
void TrackElement::incOverlapCost ( Net* net, TrackCost& cost ) const
{
if (not _track or (getNet() == net)) return;
_overlapCostCallback( this, cost );
}
string TrackElement::_getTypeName () const
{ return "TrackElement"; }
string TrackElement::_getString () const
{ return "<"+_getTypeName()+">"; }
Record* TrackElement::_getRecord () const
{
Record* record = new Record( _getString() );
record->add( getSlot( "_flags", _track ) );
record->add( getSlot( "_track", _track ) );
record->add( getSlot( "_index", _index ) );
record->add( DbU::getValueSlot( "_sourceU", &_sourceU ) );
record->add( DbU::getValueSlot( "_targetU", &_targetU ) );
return record;
}
} // Kite namespace.