* ./Kite:
- New: In BuildPowerRails, special processing for the power ring segments. The "diagonal" of vias at each corner is causing a misbehavior of the routing algorithm (due to fully saturated GCells in one direction). As a temporary fix, extend the segments so they form a "square corner". (problem arise on "d_in_i(22)"). - New: In RoutingEvent::_processNegociate, disable the "isForcedToHint()" feature. No noticeable loss of quality or speed. - New: In TrackElement/TrackSegment, wraps the AutoSegment parent's mechanism. Allows to gets the DataNegociate of either the segment or it's parent. - New: State::solveFullBlockages(), dedicated method to solves the case when all the allowed tracks of a segment are blocked, tries to moves up local segments and to break-up global ones. - New: RoutingEventLoop, a more sophisticated way to detect looping. Maintain a dynamic histogram of the last N (default 10) segments routeds, with the count of how many times they have occurred. If that count exeed 40, we *may* be facing a loop. - Change: In State::conflictSolve1, implement new policy. The global segments no more can be broken by local ones. The idea behind is that breaking a global on the request of a local will only produce more cluttering in the GCell. Globals must be keep straigth pass through, especially inside near-saturated GCells. Globals breaking however can occurs at another global's request. - Change: In TrackCost, implement the new policy about locals segments that cannot break globals segments. The sorting class now accept flags to modulate the sorting function. Two options avalaibles: IgnoreAxisWeigth (to uses for strap segments) and DiscardGlobals (to uses with locals). - Change: In TrackCost, the "distance to fixed" have now an upper bound of 50 lambdas (no need to be greater because it means it's outside the begin & en GCells). Take account not only of fixed segment, but also of placed segments which makes bound. - Bug: In Track::_check(), while calling each individual TrackSegment check, uses it as the *first* argument of the "or", otherwise it may not be called. - Bug: In ProtectRoutingPad, loop over segment Collections while modificating it was producing non-deterministic results. The fact that a collection must be not modificated while beeing iterated is becoming a more and more painful problem.
This commit is contained in:
parent
8faade8bc6
commit
3c9d064fd8
|
@ -73,6 +73,7 @@ namespace {
|
||||||
using Hurricane::Technology;
|
using Hurricane::Technology;
|
||||||
using Hurricane::DataBase;
|
using Hurricane::DataBase;
|
||||||
using CRL::AllianceFramework;
|
using CRL::AllianceFramework;
|
||||||
|
using Katabatic::ChipTools;
|
||||||
using namespace Kite;
|
using namespace Kite;
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,6 +328,7 @@ namespace {
|
||||||
public:
|
public:
|
||||||
Plane ( const Layer*, RoutingPlane* );
|
Plane ( const Layer*, RoutingPlane* );
|
||||||
~Plane ();
|
~Plane ();
|
||||||
|
inline const Layer* getLayer () const;
|
||||||
inline RoutingPlane* getRoutingPlane ();
|
inline RoutingPlane* getRoutingPlane ();
|
||||||
inline Constant::Direction getDirection () const;
|
inline Constant::Direction getDirection () const;
|
||||||
void merge ( const Box&, Net* );
|
void merge ( const Box&, Net* );
|
||||||
|
@ -596,6 +598,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Layer* PowerRailsPlanes::Plane::getLayer () const { return _layer; }
|
||||||
inline RoutingPlane* PowerRailsPlanes::Plane::getRoutingPlane () { return _routingPlane; }
|
inline RoutingPlane* PowerRailsPlanes::Plane::getRoutingPlane () { return _routingPlane; }
|
||||||
inline Constant::Direction PowerRailsPlanes::Plane::getDirection () const { return (Constant::Direction)_routingPlane->getDirection(); }
|
inline Constant::Direction PowerRailsPlanes::Plane::getDirection () const { return (Constant::Direction)_routingPlane->getDirection(); }
|
||||||
|
|
||||||
|
@ -749,16 +752,20 @@ namespace {
|
||||||
, const Box& area
|
, const Box& area
|
||||||
, const Transformation& transformation
|
, const Transformation& transformation
|
||||||
);
|
);
|
||||||
|
void ringAddToPowerRails ();
|
||||||
virtual void doQuery ();
|
virtual void doQuery ();
|
||||||
inline void doLayout ();
|
inline void doLayout ();
|
||||||
inline unsigned int getGoMatchCount () const;
|
inline unsigned int getGoMatchCount () const;
|
||||||
private:
|
private:
|
||||||
AllianceFramework* _framework;
|
AllianceFramework* _framework;
|
||||||
KiteEngine* _kite;
|
KiteEngine* _kite;
|
||||||
RoutingGauge* _routingGauge;
|
RoutingGauge* _routingGauge;
|
||||||
PowerRailsPlanes _powerRailsPlanes;
|
const ChipTools& _chipTools;
|
||||||
bool _isBlockagePlane;
|
PowerRailsPlanes _powerRailsPlanes;
|
||||||
unsigned int _goMatchCount;
|
bool _isBlockagePlane;
|
||||||
|
vector<const Segment*> _hRingSegments;
|
||||||
|
vector<const Segment*> _vRingSegments;
|
||||||
|
unsigned int _goMatchCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -767,8 +774,11 @@ namespace {
|
||||||
, _framework (AllianceFramework::get())
|
, _framework (AllianceFramework::get())
|
||||||
, _kite (kite)
|
, _kite (kite)
|
||||||
, _routingGauge (kite->getConfiguration()->getRoutingGauge())
|
, _routingGauge (kite->getConfiguration()->getRoutingGauge())
|
||||||
|
, _chipTools (kite->getChipTools())
|
||||||
, _powerRailsPlanes(kite)
|
, _powerRailsPlanes(kite)
|
||||||
, _isBlockagePlane (false)
|
, _isBlockagePlane (false)
|
||||||
|
, _hRingSegments ()
|
||||||
|
, _vRingSegments ()
|
||||||
, _goMatchCount (0)
|
, _goMatchCount (0)
|
||||||
{
|
{
|
||||||
setCell ( kite->getCell() );
|
setCell ( kite->getCell() );
|
||||||
|
@ -802,6 +812,7 @@ namespace {
|
||||||
{
|
{
|
||||||
if ( not _powerRailsPlanes.getActivePlane() ) return;
|
if ( not _powerRailsPlanes.getActivePlane() ) return;
|
||||||
Query::doQuery ();
|
Query::doQuery ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -844,6 +855,21 @@ namespace {
|
||||||
ltrace(300) << " Merging PowerRail element: " << segment << endl;
|
ltrace(300) << " Merging PowerRail element: " << segment << endl;
|
||||||
|
|
||||||
Box bb = segment->getBoundingBox ( basicLayer );
|
Box bb = segment->getBoundingBox ( basicLayer );
|
||||||
|
|
||||||
|
unsigned int depth = _routingGauge->getLayerDepth ( segment->getLayer() );
|
||||||
|
|
||||||
|
if ( _chipTools.isChip()
|
||||||
|
and ((depth == 2) or (depth == 3))
|
||||||
|
and (segment->getWidth () == DbU::lambda( 12.0))
|
||||||
|
and (segment->getLength() > DbU::lambda(200.0))
|
||||||
|
and (_kite->getChipTools().getCorona().contains(bb)) ) {
|
||||||
|
switch ( depth ) {
|
||||||
|
case 2: _vRingSegments.push_back ( segment ); break; // M3 V.
|
||||||
|
case 3: _hRingSegments.push_back ( segment ); break; // M4 H.
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
transformation.applyOn ( bb );
|
transformation.applyOn ( bb );
|
||||||
|
|
||||||
_powerRailsPlanes.merge ( bb, rootNet );
|
_powerRailsPlanes.merge ( bb, rootNet );
|
||||||
|
@ -864,6 +890,51 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QueryPowerRails::ringAddToPowerRails ()
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( not _hRingSegments.empty() ) {
|
||||||
|
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(_routingGauge->getRoutingLayer(3));
|
||||||
|
setBasicLayer ( layer->getBasicLayer() );
|
||||||
|
|
||||||
|
DbU::Unit xmin = DbU::Max;
|
||||||
|
DbU::Unit xmax = DbU::Min;
|
||||||
|
vector<Box> boxes;
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<_hRingSegments.size() ; ++i ) {
|
||||||
|
boxes.push_back ( _hRingSegments[i]->getBoundingBox() );
|
||||||
|
xmin = std::min ( xmin, boxes.back().getXMin() );
|
||||||
|
xmax = std::max ( xmax, boxes.back().getXMax() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<_hRingSegments.size() ; ++i ) {
|
||||||
|
_powerRailsPlanes.merge ( Box(xmin,boxes[i].getYMin(),xmax,boxes[i].getYMax())
|
||||||
|
, _powerRailsPlanes.getRootNet(_hRingSegments[i]->getNet(),Path()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( not _vRingSegments.empty() ) {
|
||||||
|
const RegularLayer* layer = dynamic_cast<const RegularLayer*>(_routingGauge->getRoutingLayer(2));
|
||||||
|
setBasicLayer ( layer->getBasicLayer() );
|
||||||
|
|
||||||
|
DbU::Unit ymin = DbU::Max;
|
||||||
|
DbU::Unit ymax = DbU::Min;
|
||||||
|
vector<Box> boxes;
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<_vRingSegments.size() ; ++i ) {
|
||||||
|
boxes.push_back ( _vRingSegments[i]->getBoundingBox() );
|
||||||
|
ymin = std::min ( ymin, boxes.back().getYMin() );
|
||||||
|
ymax = std::max ( ymax, boxes.back().getYMax() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<_vRingSegments.size() ; ++i ) {
|
||||||
|
_powerRailsPlanes.merge ( Box(boxes[i].getXMin(),ymin,boxes[i].getXMax(),ymax)
|
||||||
|
, _powerRailsPlanes.getRootNet(_vRingSegments[i]->getNet(),Path()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QueryPowerRails::rubberCallback ( Rubber* )
|
void QueryPowerRails::rubberCallback ( Rubber* )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -910,6 +981,7 @@ namespace Kite {
|
||||||
query.setBasicLayer ( *iLayer );
|
query.setBasicLayer ( *iLayer );
|
||||||
query.doQuery ();
|
query.doQuery ();
|
||||||
}
|
}
|
||||||
|
query.ringAddToPowerRails ();
|
||||||
query.doLayout ();
|
query.doLayout ();
|
||||||
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
|
cmess1 << " - " << query.getGoMatchCount() << " power rails elements found." << endl;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
kite/RoutingEvent.h
|
kite/RoutingEvent.h
|
||||||
kite/RoutingEventQueue.h
|
kite/RoutingEventQueue.h
|
||||||
kite/RoutingEventHistory.h
|
kite/RoutingEventHistory.h
|
||||||
|
kite/RoutingEventLoop.h
|
||||||
kite/RoutingPlane.h
|
kite/RoutingPlane.h
|
||||||
kite/NegociateWindow.h
|
kite/NegociateWindow.h
|
||||||
kite/Configuration.h
|
kite/Configuration.h
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
RoutingEvent.cpp
|
RoutingEvent.cpp
|
||||||
RoutingEventQueue.cpp
|
RoutingEventQueue.cpp
|
||||||
RoutingEventHistory.cpp
|
RoutingEventHistory.cpp
|
||||||
|
RoutingEventLoop.cpp
|
||||||
RoutingPlane.cpp
|
RoutingPlane.cpp
|
||||||
BuildPowerRails.cpp
|
BuildPowerRails.cpp
|
||||||
ProtectRoutingPads.cpp
|
ProtectRoutingPads.cpp
|
||||||
|
|
|
@ -77,11 +77,12 @@ namespace Kite {
|
||||||
threshold = 2*50;
|
threshold = 2*50;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
threshold = 29*50;
|
threshold = 30*50;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_globalMinBreaks[i] = DbU::lambda(Cfg::getParamInt(paramName.str(),threshold)->asInt());
|
Cfg::getParamDouble(paramName.str())->setDouble(threshold);
|
||||||
|
_globalMinBreaks[i] = DbU::lambda (Cfg::getParamDouble(paramName.str())->asDouble());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,9 +240,7 @@ namespace Kite {
|
||||||
|
|
||||||
|
|
||||||
string Configuration::_getTypeName () const
|
string Configuration::_getTypeName () const
|
||||||
{
|
{ return "Configuration"; }
|
||||||
return "Configuration";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
string Configuration::_getString () const
|
string Configuration::_getString () const
|
||||||
|
@ -258,6 +257,24 @@ namespace Kite {
|
||||||
{
|
{
|
||||||
Record* record = _base->_getRecord();
|
Record* record = _base->_getRecord();
|
||||||
//record->add ( getSlot ( "_rg" , _rg ) );
|
//record->add ( getSlot ( "_rg" , _rg ) );
|
||||||
|
if ( record ) {
|
||||||
|
record->add ( getSlot("_edgeCapacityPercent",_edgeCapacityPercent) );
|
||||||
|
record->add ( getSlot("_ripupCost" ,_ripupCost ) );
|
||||||
|
record->add ( getSlot("_eventsLimit" ,_eventsLimit ) );
|
||||||
|
record->add ( getSlot("_edgeCapacityPercent",_edgeCapacityPercent) );
|
||||||
|
|
||||||
|
record->add ( getSlot("_ripupLimits[StrapRipupLimit]" ,_ripupLimits[StrapRipupLimit] ) );
|
||||||
|
record->add ( getSlot("_ripupLimits[LocalRipupLimit]" ,_ripupLimits[LocalRipupLimit] ) );
|
||||||
|
record->add ( getSlot("_ripupLimits[GlobalRipupLimit]" ,_ripupLimits[GlobalRipupLimit] ) );
|
||||||
|
record->add ( getSlot("_ripupLimits[LongGlobalRipupLimit]",_ripupLimits[LongGlobalRipupLimit]) );
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<MaxMetalDepth ; ++i ) {
|
||||||
|
ostringstream paramName;
|
||||||
|
paramName << "metal" << (i+1) << "MinBreak";
|
||||||
|
|
||||||
|
record->add ( DbU::getValueSlot(paramName.str(),&_globalMinBreaks[i]) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
|
@ -459,19 +459,23 @@ namespace Kite {
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_soper_se(20)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_soper_se(20)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_res_re(20)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_res_re(20)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_addsub32_carith_se_gi_1_29" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_addsub32_carith_se_gi_1_29" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_instaddbracry_sd_gi_1_21" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.instaddbracry_sd.gi_1_29" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.instseqadr_sd.pi_2_26" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_addsub32_carith_se_pi_3_29" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_addsub32_carith_se_pi_3_29" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_res_se(28)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_dp_res_se(28)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.etat32_otheri_sd_2.enx" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.etat32_otheri_sd_2.enx" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.yoper_se(26)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.yoper_se(13)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.toper_se(5)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.toper_se(5)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.soper_se(20)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.shift32_rshift_se.muxoutput(68)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.imdsgn_sd0" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.res_re(12)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.res_re(12)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.res_re(20)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.res_re(20)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.nextpc_rd(21)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.nextpc_rd(21)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "addr_i(1)" );
|
//DebugSession::addToTrace ( getCell(), "addr_i(1)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.opcod_rd(1)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.opcod_rd(1)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.otheri_sd(29)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.otheri_sd(29)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "d_in_i(11)" );
|
//DebugSession::addToTrace ( getCell(), "d_in_i(22)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "ng_i" );
|
//DebugSession::addToTrace ( getCell(), "ng_i" );
|
||||||
//DebugSession::addToTrace ( getCell(), "d_out_i(14)" );
|
//DebugSession::addToTrace ( getCell(), "d_out_i(14)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "d_out_i(19)" );
|
//DebugSession::addToTrace ( getCell(), "d_out_i(19)" );
|
||||||
|
@ -479,13 +483,33 @@ namespace Kite {
|
||||||
//DebugSession::addToTrace ( getCell(), "dout_e_i(2)" );
|
//DebugSession::addToTrace ( getCell(), "dout_e_i(2)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.aux44" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.aux44" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.na4_x1_11_sig" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.na4_x1_11_sig" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.nxr2_x1_7_sig" );
|
||||||
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.rsdnbr_sd(14)" );
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.rsdnbr_sd(14)" );
|
||||||
//DebugSession::addToTrace ( getCell(), "d_out_i(27)" );
|
//DebugSession::addToTrace ( getCell(), "d_out_i(28)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_1m_ct_mbk_buf_opcod_sd_0" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.break_re" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "d_atype_i(0)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "addr_i(0)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.i_write_sm" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_i_ri(11)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_opcod_rd(0)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.no4_x1_7_sig" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.i_ri(5)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_aux144" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_aux143" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.aux78" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_hold_si" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_ct.not_i_ri(30)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.data_rm(0)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.toper_se(0)" );
|
||||||
|
//DebugSession::addToTrace ( getCell(), "mips_r3000_core.mips_r3000_1m_dp.res_se(17)" );
|
||||||
|
|
||||||
createDetailedGrid ();
|
createDetailedGrid ();
|
||||||
buildPowerRails ();
|
buildPowerRails ();
|
||||||
protectRoutingPads ();
|
protectRoutingPads ();
|
||||||
|
|
||||||
|
Session::revalidate ();
|
||||||
|
|
||||||
if ( mode == LoadGlobalSolution ) {
|
if ( mode == LoadGlobalSolution ) {
|
||||||
_knik->loadSolution ();
|
_knik->loadSolution ();
|
||||||
} else {
|
} else {
|
||||||
|
@ -665,7 +689,7 @@ namespace Kite {
|
||||||
bool coherency = true;
|
bool coherency = true;
|
||||||
coherency = coherency && KatabaticEngine::_check ( message );
|
coherency = coherency && KatabaticEngine::_check ( message );
|
||||||
for ( size_t i=0 ; i<_routingPlanes.size() ; i++ )
|
for ( size_t i=0 ; i<_routingPlanes.size() ; i++ )
|
||||||
coherency = _routingPlanes[i]->_check(overlap) && coherency;
|
coherency = _routingPlanes[i]->_check(overlap) and coherency;
|
||||||
|
|
||||||
Katabatic::Session* ktbtSession = Session::base ();
|
Katabatic::Session* ktbtSession = Session::base ();
|
||||||
forEach ( Net*, inet, getCell()->getNets() ) {
|
forEach ( Net*, inet, getCell()->getNets() ) {
|
||||||
|
@ -687,7 +711,7 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CHECK_DATABASE)
|
#if defined(CHECK_DATABASE)
|
||||||
//Session::getKiteEngine()->setInterrupt ( !coherency );
|
//Session::getKiteEngine()->setInterrupt ( not coherency );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return coherency;
|
return coherency;
|
||||||
|
@ -823,7 +847,10 @@ namespace Kite {
|
||||||
{
|
{
|
||||||
Record* record = KatabaticEngine::_getRecord ();
|
Record* record = KatabaticEngine::_getRecord ();
|
||||||
|
|
||||||
record->add ( getSlot ( "_routingPlanes", &_routingPlanes ) );
|
if ( record ) {
|
||||||
|
record->add ( getSlot ( "_routingPlanes", &_routingPlanes ) );
|
||||||
|
record->add ( getSlot ( "_configuration", _configuration ) );
|
||||||
|
}
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "kite/RoutingPlane.h"
|
#include "kite/RoutingPlane.h"
|
||||||
#include "kite/RoutingEventQueue.h"
|
#include "kite/RoutingEventQueue.h"
|
||||||
#include "kite/RoutingEventHistory.h"
|
#include "kite/RoutingEventHistory.h"
|
||||||
|
#include "kite/RoutingEventLoop.h"
|
||||||
#include "kite/NegociateWindow.h"
|
#include "kite/NegociateWindow.h"
|
||||||
#include "kite/KiteEngine.h"
|
#include "kite/KiteEngine.h"
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ namespace {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( cost.getInterval().getVMax() > intersect.getVMax() ) cost.setLeftOverlap();
|
if ( cost.getInterval().getVMax() > intersect.getVMax() ) cost.setLeftOverlap();
|
||||||
if ( cost.getInterval().getVMin() < intersect.getVMin() ) cost.setRightOverlap();
|
if ( cost.getInterval().getVMin() < intersect.getVMin() ) cost.setRightOverlap();
|
||||||
|
|
||||||
|
@ -92,6 +94,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( segment->isGlobal() ) {
|
||||||
|
//if ( data->getState() >= DataNegociate::ConflictSolve1 ) {
|
||||||
|
cost.setOverlapGlobal();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
// if ( data->getRipupCount() > 3 ) {
|
// if ( data->getRipupCount() > 3 ) {
|
||||||
// ltrace(200) << "Infinite cost from: " << segment << endl;
|
// ltrace(200) << "Infinite cost from: " << segment << endl;
|
||||||
// cost.setFixed ();
|
// cost.setFixed ();
|
||||||
|
@ -164,6 +172,7 @@ namespace Kite {
|
||||||
, _segments ()
|
, _segments ()
|
||||||
, _eventQueue ()
|
, _eventQueue ()
|
||||||
, _eventHistory()
|
, _eventHistory()
|
||||||
|
, _eventLoop (10,50)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -378,14 +387,15 @@ namespace Kite {
|
||||||
while ( not _eventQueue.empty() and not isInterrupted() ) {
|
while ( not _eventQueue.empty() and not isInterrupted() ) {
|
||||||
RoutingEvent* event = _eventQueue.pop ();
|
RoutingEvent* event = _eventQueue.pop ();
|
||||||
|
|
||||||
event->process ( _eventQueue, _eventHistory );
|
event->process ( _eventQueue, _eventHistory, _eventLoop );
|
||||||
if (tty::enabled()) {
|
if (tty::enabled()) {
|
||||||
cmess1 << " <event:" << tty::bold << setw(7) << setfill('0')
|
cmess2 << " <event:" << tty::bold << setw(7) << setfill('0')
|
||||||
<< RoutingEvent::getProcesseds() << setfill(' ') << tty::reset << ">" << tty::cr;
|
<< RoutingEvent::getProcesseds() << setfill(' ') << tty::reset << ">" << tty::cr;
|
||||||
cmess1.flush ();
|
cmess2.flush ();
|
||||||
} else {
|
} else {
|
||||||
cmess2 << " <event:" << setw(7) << setfill('0')
|
cmess2 << " <event:" << setw(7) << setfill('0')
|
||||||
<< RoutingEvent::getProcesseds() << setfill(' ') << "> id:"
|
<< RoutingEvent::getProcesseds() << setfill(' ') << "> @"
|
||||||
|
<< DbU::getValueString(event->getSegment()->getAxis()) << " id:"
|
||||||
<< event->getSegment()->getId() << " "
|
<< event->getSegment()->getId() << " "
|
||||||
<< event->getSegment()->getNet()->getName()
|
<< event->getSegment()->getNet()->getName()
|
||||||
<< endl;
|
<< endl;
|
||||||
|
@ -410,7 +420,7 @@ namespace Kite {
|
||||||
count++;
|
count++;
|
||||||
event->setProcessed ( false );
|
event->setProcessed ( false );
|
||||||
event->setMode ( RoutingEvent::PostPack );
|
event->setMode ( RoutingEvent::PostPack );
|
||||||
event->process ( _eventQueue, _eventHistory );
|
event->process ( _eventQueue, _eventHistory, _eventLoop );
|
||||||
|
|
||||||
if (tty::enabled()) {
|
if (tty::enabled()) {
|
||||||
cmess1 << " <event:"
|
cmess1 << " <event:"
|
||||||
|
@ -503,7 +513,7 @@ namespace Kite {
|
||||||
|
|
||||||
const Katabatic::GCellVector* gcells = getKiteEngine()->getGCellGrid()->getGCellVector();
|
const Katabatic::GCellVector* gcells = getKiteEngine()->getGCellGrid()->getGCellVector();
|
||||||
|
|
||||||
getKiteEngine()->getGCellGrid()->setDensityMode ( Katabatic::GCellGrid::AverageHVDensity );
|
getKiteEngine()->getGCellGrid()->setDensityMode ( Katabatic::GCellGrid::MaxHVDensity );
|
||||||
for ( size_t igcell=0 ; igcell<(*gcells).size() ; ++igcell ) {
|
for ( size_t igcell=0 ; igcell<(*gcells).size() ; ++igcell ) {
|
||||||
densityHistogram->addSample ( (*gcells)[igcell]->getDensity(), 0 );
|
densityHistogram->addSample ( (*gcells)[igcell]->getDensity(), 0 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,28 +85,34 @@ namespace {
|
||||||
|
|
||||||
if ( CatalogExtension::isPad(masterNet->getCell()) ) return;
|
if ( CatalogExtension::isPad(masterNet->getCell()) ) return;
|
||||||
|
|
||||||
|
vector<Segment*> segments;
|
||||||
|
|
||||||
forEach ( Segment*, isegment, masterNet->getSegments() ) {
|
forEach ( Segment*, isegment, masterNet->getSegments() ) {
|
||||||
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(isegment->getLayer());
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(isegment->getLayer());
|
||||||
if ( plane == NULL ) {
|
if ( plane == NULL ) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int direction = plane->getDirection();
|
|
||||||
DbU::Unit wireWidth = plane->getLayerGauge()->getWireWidth();
|
|
||||||
DbU::Unit delta = plane->getLayerGauge()->getHalfPitch()
|
|
||||||
+ wireWidth/2
|
|
||||||
- DbU::lambda(0.1);
|
|
||||||
DbU::Unit extension = isegment->getLayer()->getExtentionCap();
|
|
||||||
|
|
||||||
if ( usedComponent == dynamic_cast<Component*>(*isegment) ) continue;
|
if ( usedComponent == dynamic_cast<Component*>(*isegment) ) continue;
|
||||||
if ( not NetExternalComponents::isExternal(*isegment) ) continue;
|
if ( not NetExternalComponents::isExternal(*isegment) ) continue;
|
||||||
|
|
||||||
//cinfo << "Protecting " << *isegment << endl;
|
//cerr << "Looking " << (void*)*isegment << ":" << *isegment << endl;
|
||||||
|
|
||||||
|
segments.push_back ( *isegment );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<segments.size() ; ++i ) {
|
||||||
|
//cerr << "Protecting " << segments[i] << endl;
|
||||||
|
|
||||||
|
RoutingPlane* plane = Session::getKiteEngine()->getRoutingPlaneByLayer(segments[i]->getLayer());
|
||||||
|
unsigned int direction = plane->getDirection();
|
||||||
|
DbU::Unit wireWidth = plane->getLayerGauge()->getWireWidth();
|
||||||
|
DbU::Unit delta = plane->getLayerGauge()->getHalfPitch()
|
||||||
|
+ wireWidth/2
|
||||||
|
- DbU::lambda(0.1);
|
||||||
|
DbU::Unit extension = segments[i]->getLayer()->getExtentionCap();
|
||||||
|
Box bb ( segments[i]->getBoundingBox() );
|
||||||
|
|
||||||
Box bb ( (*isegment)->getBoundingBox() );
|
|
||||||
transformation.applyOn ( bb );
|
transformation.applyOn ( bb );
|
||||||
|
cinfo << "bb: " << bb << endl;
|
||||||
//cinfo << "bb: " << bb << endl;
|
|
||||||
|
|
||||||
if ( direction == Constant::Horizontal ) {
|
if ( direction == Constant::Horizontal ) {
|
||||||
DbU::Unit axisMin = bb.getYMin() - delta;
|
DbU::Unit axisMin = bb.getYMin() - delta;
|
||||||
|
@ -115,61 +121,14 @@ namespace {
|
||||||
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
||||||
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
||||||
Horizontal* segment = Horizontal::create ( rp->getNet()
|
Horizontal* segment = Horizontal::create ( rp->getNet()
|
||||||
, isegment->getLayer()
|
, segments[i]->getLayer()
|
||||||
, track->getAxis()
|
, track->getAxis()
|
||||||
, wireWidth
|
, wireWidth
|
||||||
, bb.getXMin()+extension
|
, bb.getXMin()+extension
|
||||||
, bb.getXMax()-extension
|
, bb.getXMax()-extension
|
||||||
);
|
);
|
||||||
// TrackElement* element =
|
TrackFixedSegment::create ( track, segment );
|
||||||
TrackFixedSegment::create ( track, segment );
|
|
||||||
//cinfo << " Rp Protect:" << track << "+" << element << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
|
||||||
// for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
|
||||||
// Point sourcePosition (bb.getXMin()+extension,track->getAxis());
|
|
||||||
// Point targetPosition (bb.getXMax()-extension,track->getAxis());
|
|
||||||
|
|
||||||
// Katabatic::GCell* sourceGCell = Session::getKatabatic()->getGCellGrid()->getGCell ( sourcePosition );
|
|
||||||
// Katabatic::GCell* targetGCell = Session::getKatabatic()->getGCellGrid()->getGCell ( targetPosition );
|
|
||||||
|
|
||||||
// cinfo << " S: " << sourceGCell << " from " << sourcePosition << endl;
|
|
||||||
// cinfo << " T: " << targetGCell << " from " << targetPosition << endl;
|
|
||||||
|
|
||||||
// unsigned int segmentType
|
|
||||||
// = (sourceGCell == targetGCell) ? AutoSegment::Local : AutoSegment::Global;
|
|
||||||
|
|
||||||
// AutoContact* source = AutoContact::fromRp ( sourceGCell
|
|
||||||
// , rp
|
|
||||||
// , rp->getLayer()
|
|
||||||
// , sourcePosition
|
|
||||||
// , DbU::lambda(1.0), DbU::lambda(1.0)
|
|
||||||
// , true
|
|
||||||
// );
|
|
||||||
|
|
||||||
// AutoContact* target = AutoContact::fromRp ( targetGCell
|
|
||||||
// , rp
|
|
||||||
// , rp->getLayer()
|
|
||||||
// , targetPosition
|
|
||||||
// , DbU::lambda(1.0), DbU::lambda(1.0)
|
|
||||||
// , true
|
|
||||||
// );
|
|
||||||
|
|
||||||
// AutoSegment* segment = AutoSegment::create ( source
|
|
||||||
// , target
|
|
||||||
// , Constant::Horizontal
|
|
||||||
// , segmentType
|
|
||||||
// , true
|
|
||||||
// , false
|
|
||||||
// );
|
|
||||||
// segment->setLayer ( isegment->getLayer() );
|
|
||||||
// segment->setFixed ( true );
|
|
||||||
|
|
||||||
// bool created = true;
|
|
||||||
// TrackElement* element = TrackSegment::create ( segment, track, created );
|
|
||||||
// cinfo << " Rp Protect " << track << "+" << element << endl;
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
DbU::Unit axisMin = bb.getXMin() - delta;
|
DbU::Unit axisMin = bb.getXMin() - delta;
|
||||||
DbU::Unit axisMax = bb.getXMax() + delta;
|
DbU::Unit axisMax = bb.getXMax() + delta;
|
||||||
|
@ -177,63 +136,14 @@ namespace {
|
||||||
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
||||||
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
||||||
Vertical* segment = Vertical::create ( rp->getNet()
|
Vertical* segment = Vertical::create ( rp->getNet()
|
||||||
, isegment->getLayer()
|
, segments[i]->getLayer()
|
||||||
, track->getAxis()
|
, track->getAxis()
|
||||||
, wireWidth
|
, wireWidth
|
||||||
, bb.getYMin()+extension
|
, bb.getYMin()+extension
|
||||||
, bb.getYMax()-extension
|
, bb.getYMax()-extension
|
||||||
);
|
);
|
||||||
// TrackElement* element =
|
TrackFixedSegment::create ( track, segment );
|
||||||
TrackFixedSegment::create ( track, segment );
|
|
||||||
//cinfo << " Rp Protect:" << track << "+" << element << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track* track = plane->getTrackByPosition ( axisMin, Constant::Superior );
|
|
||||||
// for ( ; track and (track->getAxis() <= axisMax) ; track = track->getNext() ) {
|
|
||||||
// cinfo << " Track Axis: " << DbU::getValueString(track->getAxis()) << endl;
|
|
||||||
|
|
||||||
// Point sourcePosition (track->getAxis(),bb.getYMin()+extension);
|
|
||||||
// Point targetPosition (track->getAxis(),bb.getYMax()-extension);
|
|
||||||
|
|
||||||
// Katabatic::GCell* sourceGCell = Session::getKatabatic()->getGCellGrid()->getGCell ( sourcePosition );
|
|
||||||
// Katabatic::GCell* targetGCell = Session::getKatabatic()->getGCellGrid()->getGCell ( targetPosition );
|
|
||||||
|
|
||||||
// cinfo << " S: " << sourceGCell << " from " << sourcePosition << endl;
|
|
||||||
// cinfo << " T: " << targetGCell << " from " << targetPosition << endl;
|
|
||||||
|
|
||||||
// unsigned int segmentType
|
|
||||||
// = (sourceGCell == targetGCell) ? AutoSegment::Local : AutoSegment::Global;
|
|
||||||
|
|
||||||
// AutoContact* source = AutoContact::fromRp ( sourceGCell
|
|
||||||
// , rp
|
|
||||||
// , rp->getLayer()
|
|
||||||
// , sourcePosition
|
|
||||||
// , DbU::lambda(1.0), DbU::lambda(1.0)
|
|
||||||
// , true
|
|
||||||
// );
|
|
||||||
|
|
||||||
// AutoContact* target = AutoContact::fromRp ( targetGCell
|
|
||||||
// , rp
|
|
||||||
// , rp->getLayer()
|
|
||||||
// , targetPosition
|
|
||||||
// , DbU::lambda(1.0), DbU::lambda(1.0)
|
|
||||||
// , true
|
|
||||||
// );
|
|
||||||
|
|
||||||
// AutoSegment* segment = AutoSegment::create ( source
|
|
||||||
// , target
|
|
||||||
// , Constant::Vertical
|
|
||||||
// , segmentType
|
|
||||||
// , true
|
|
||||||
// , false
|
|
||||||
// );
|
|
||||||
// segment->setLayer ( isegment->getLayer() );
|
|
||||||
// segment->setFixed ( true );
|
|
||||||
|
|
||||||
// bool created = true;
|
|
||||||
// TrackElement* element = TrackSegment::create ( segment, track, created );
|
|
||||||
// cinfo << " Rp Protect: " << track << "+" << element << endl;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,11 +167,18 @@ namespace Kite {
|
||||||
cmess1 << " o Protect external components not useds as RoutingPads." << endl;
|
cmess1 << " o Protect external components not useds as RoutingPads." << endl;
|
||||||
|
|
||||||
forEach ( Net*, inet, getCell()->getNets() ) {
|
forEach ( Net*, inet, getCell()->getNets() ) {
|
||||||
|
// cerr << *inet << " isSupply():" << (*inet)->isSupply()
|
||||||
|
// << " " << (*inet)->getType()
|
||||||
|
// << endl;
|
||||||
if ( (*inet)->isSupply() ) continue;
|
if ( (*inet)->isSupply() ) continue;
|
||||||
|
|
||||||
|
vector<RoutingPad*> rps;
|
||||||
forEach ( RoutingPad*, irp, (*inet)->getRoutingPads() ) {
|
forEach ( RoutingPad*, irp, (*inet)->getRoutingPads() ) {
|
||||||
protectRoutingPad ( *irp );
|
rps.push_back ( *irp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<rps.size() ; ++i )
|
||||||
|
protectRoutingPad ( rps[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
Session::revalidate ();
|
Session::revalidate ();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -46,7 +46,6 @@ namespace Kite {
|
||||||
|
|
||||||
RoutingEventHistory::RoutingEventHistory ()
|
RoutingEventHistory::RoutingEventHistory ()
|
||||||
: _events ()
|
: _events ()
|
||||||
, _identicals(0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,19 +82,7 @@ namespace Kite {
|
||||||
|
|
||||||
|
|
||||||
void RoutingEventHistory::push ( RoutingEvent* event )
|
void RoutingEventHistory::push ( RoutingEvent* event )
|
||||||
{
|
{ _events.push_back(event); }
|
||||||
if ( _events.size() && (event->getSegment() == _events.back()->getSegment()) )
|
|
||||||
_identicals++;
|
|
||||||
else
|
|
||||||
_identicals = 0;
|
|
||||||
|
|
||||||
_events.push_back(event);
|
|
||||||
|
|
||||||
// if ( _identicals > 30 ) {
|
|
||||||
// dump ( cerr, 40 );
|
|
||||||
// throw Error("RoutingEventHistory::push(): More than 30 identicals events, we are looping.");
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void RoutingEventHistory::clear ()
|
void RoutingEventHistory::clear ()
|
||||||
|
@ -103,7 +90,6 @@ namespace Kite {
|
||||||
for ( size_t i=0 ; i < _events.size() ; i++ )
|
for ( size_t i=0 ; i < _events.size() ; i++ )
|
||||||
_events[i]->destroy();
|
_events[i]->destroy();
|
||||||
_events.clear ();
|
_events.clear ();
|
||||||
_identicals = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
||||||
|
//
|
||||||
|
// ===================================================================
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
// | |
|
||||||
|
// | 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 : "./RoutingEventLoop.cpp" |
|
||||||
|
// | *************************************************************** |
|
||||||
|
// | U p d a t e s |
|
||||||
|
// | |
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "kite/RoutingEvent.h"
|
||||||
|
#include "kite/RoutingEventLoop.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Kite {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::vector;
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
|
|
||||||
|
RoutingEventLoop::RoutingEventLoop ( size_t depth, int countLimit )
|
||||||
|
: _elements ()
|
||||||
|
, _depth (depth)
|
||||||
|
, _maxCount (0)
|
||||||
|
, _countLimit(countLimit)
|
||||||
|
, _isLooping (false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void RoutingEventLoop::update ( size_t id )
|
||||||
|
{
|
||||||
|
vector<Element>::iterator ielement = _elements.begin();
|
||||||
|
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||||
|
if ( (*ielement)._id == id ) {
|
||||||
|
// Increment an already present element.
|
||||||
|
(*ielement)._count += 1;
|
||||||
|
(*ielement)._timestamp = RoutingEvent::getProcesseds();
|
||||||
|
_maxCount = std::max ( _maxCount, (*ielement)._count );
|
||||||
|
|
||||||
|
if ( _maxCount > _countLimit ) _isLooping = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Event was not found.
|
||||||
|
if ( ielement == _elements.end() ) {
|
||||||
|
if ( _elements.size() >= _depth ) _elements.pop_back ();
|
||||||
|
_elements.push_back ( Element(id,RoutingEvent::getProcesseds()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
stable_sort ( _elements.begin(), _elements.end(), CompareByTimestamp() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RoutingEventLoop::erase ( size_t id )
|
||||||
|
{
|
||||||
|
vector<Element>::iterator ielement = _elements.begin();
|
||||||
|
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||||
|
if ( (*ielement)._id == id ) {
|
||||||
|
_elements.erase ( ielement );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_maxCount = 0;
|
||||||
|
ielement = _elements.begin();
|
||||||
|
for ( ; ielement != _elements.end() ; ++ielement ) {
|
||||||
|
_maxCount = std::max ( _maxCount, (*ielement)._count );
|
||||||
|
}
|
||||||
|
|
||||||
|
_isLooping = (_maxCount > _countLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Kite namespace.
|
|
@ -160,7 +160,7 @@ namespace Kite {
|
||||||
bool coherency = true;
|
bool coherency = true;
|
||||||
|
|
||||||
for ( size_t i=0 ; i<_tracks.size() ; i++ ) {
|
for ( size_t i=0 ; i<_tracks.size() ; i++ ) {
|
||||||
coherency = _tracks[i]->_check(overlaps) && coherency;
|
coherency = _tracks[i]->_check(overlaps) and coherency;
|
||||||
}
|
}
|
||||||
|
|
||||||
return coherency;
|
return coherency;
|
||||||
|
|
|
@ -286,7 +286,7 @@ namespace Kite {
|
||||||
|
|
||||||
TrackCost Track::getOverlapCost ( Interval interval, Net* net, size_t begin, size_t end ) const
|
TrackCost Track::getOverlapCost ( Interval interval, Net* net, size_t begin, size_t end ) const
|
||||||
{
|
{
|
||||||
TrackCost cost ( const_cast<Track*>(this), interval, begin, end );
|
TrackCost cost ( const_cast<Track*>(this), interval, begin, end, net );
|
||||||
|
|
||||||
ltrace(190) << "getOverlapCost() @" << DbU::getValueString(_axis)
|
ltrace(190) << "getOverlapCost() @" << DbU::getValueString(_axis)
|
||||||
<< " [" << DbU::getValueString(interval.getVMin())
|
<< " [" << DbU::getValueString(interval.getVMin())
|
||||||
|
@ -538,7 +538,7 @@ namespace Kite {
|
||||||
coherency = false;
|
coherency = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
coherency = coherency && _segments[i]->_check ();
|
coherency = _segments[i]->_check () and coherency;
|
||||||
} else {
|
} else {
|
||||||
cerr << "[CHECK] Hole at position " << i << "." << endl;
|
cerr << "[CHECK] Hole at position " << i << "." << endl;
|
||||||
holes = true;
|
holes = true;
|
||||||
|
@ -547,7 +547,7 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !holes )
|
if ( !holes )
|
||||||
coherency = coherency && (checkOverlap(overlaps) == 0);
|
coherency = (checkOverlap(overlaps) == 0) and coherency;
|
||||||
|
|
||||||
return coherency;
|
return coherency;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace Kite {
|
||||||
, const Interval& interval
|
, const Interval& interval
|
||||||
, size_t begin
|
, size_t begin
|
||||||
, size_t end
|
, size_t end
|
||||||
|
, Net* net
|
||||||
)
|
)
|
||||||
: _track (track)
|
: _track (track)
|
||||||
, _begin (begin)
|
, _begin (begin)
|
||||||
|
@ -63,29 +64,41 @@ namespace Kite {
|
||||||
, _overlap (false)
|
, _overlap (false)
|
||||||
, _leftOverlap (false)
|
, _leftOverlap (false)
|
||||||
, _rightOverlap (false)
|
, _rightOverlap (false)
|
||||||
|
, _overlapGlobal (false)
|
||||||
, _terminals (0)
|
, _terminals (0)
|
||||||
, _delta (-interval.getSize())
|
, _delta (-interval.getSize())
|
||||||
, _deltaShared (0)
|
, _deltaShared (0)
|
||||||
, _deltaPerpand (0)
|
, _deltaPerpand (0)
|
||||||
, _axisWeight (0)
|
, _axisWeight (0)
|
||||||
, _distanceToFixed(DbU::Max)
|
, _distanceToFixed(DbU::lambda(100.0))
|
||||||
, _dataState (0)
|
, _dataState (0)
|
||||||
, _ripupCount (0)
|
, _ripupCount (0)
|
||||||
{
|
{
|
||||||
TrackElement* neighbor;
|
TrackElement* neighbor;
|
||||||
if ( _begin != Track::NPOS ) {
|
if ( _begin != Track::NPOS ) {
|
||||||
neighbor = _track->getSegment(_begin);
|
neighbor = _track->getSegment(_begin);
|
||||||
if ( neighbor && neighbor->isFixed() ) {
|
if ( neighbor and (neighbor->getNet() != net) ) {
|
||||||
if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
|
DbU::Unit distance = interval.getVMin() - neighbor->getTargetU();
|
||||||
_distanceToFixed += interval.getVMin() - neighbor->getTargetU();
|
if ( distance < DbU::lambda(50.0) )
|
||||||
|
_distanceToFixed = distance;
|
||||||
}
|
}
|
||||||
|
// if ( neighbor and neighbor->isFixed() ) {
|
||||||
|
// if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
|
||||||
|
// _distanceToFixed += interval.getVMin() - neighbor->getTargetU();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if ( _end != Track::NPOS ) {
|
if ( _end != Track::NPOS ) {
|
||||||
neighbor = _track->getSegment(_end);
|
neighbor = _track->getSegment(_end);
|
||||||
if ( neighbor && neighbor->isFixed() ) {
|
if ( neighbor and (neighbor->getNet() != net) ) {
|
||||||
if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
|
DbU::Unit distance = neighbor->getSourceU() - interval.getVMax();
|
||||||
_distanceToFixed += neighbor->getSourceU() - interval.getVMax();
|
if ( _distanceToFixed == DbU::lambda(100.0) ) _distanceToFixed = 0;
|
||||||
|
if ( distance < DbU::lambda(50.0) )
|
||||||
|
_distanceToFixed += distance;
|
||||||
}
|
}
|
||||||
|
// if ( neighbor and neighbor->isFixed() ) {
|
||||||
|
// if ( _distanceToFixed == DbU::Max ) _distanceToFixed = 0;
|
||||||
|
// _distanceToFixed += neighbor->getSourceU() - interval.getVMax();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,36 +113,36 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool operator< ( const TrackCost& lhs, const TrackCost& rhs )
|
bool TrackCost::Compare::operator() ( const TrackCost& lhs, const TrackCost& rhs )
|
||||||
{
|
{
|
||||||
if ( lhs._infinite xor rhs._infinite ) return rhs._infinite;
|
if ( lhs._infinite xor rhs._infinite ) return rhs._infinite;
|
||||||
|
|
||||||
|
if ( (_flags & TrackCost::DiscardGlobals)
|
||||||
|
and (lhs._overlapGlobal xor rhs._overlapGlobal) )
|
||||||
|
return rhs._overlapGlobal;
|
||||||
|
|
||||||
if ( lhs._hardOverlap xor rhs._hardOverlap ) return rhs._hardOverlap;
|
if ( lhs._hardOverlap xor rhs._hardOverlap ) return rhs._hardOverlap;
|
||||||
|
|
||||||
int lhsRipupCost = (lhs._dataState<<2) + lhs._ripupCount;
|
if ( lhs._ripupCount + (int)Session::getRipupCost() < rhs._ripupCount ) return true;
|
||||||
int rhsRipupCost = (rhs._dataState<<2) + rhs._ripupCount;
|
if ( lhs._ripupCount > (int)Session::getRipupCost() + rhs._ripupCount ) return false;
|
||||||
|
|
||||||
// if ( lhs._ripupCount + (int)Session::getRipupCost() < rhs._ripupCount ) return true;
|
//int lhsRipupCost = (lhs._dataState<<2) + lhs._ripupCount;
|
||||||
// if ( lhs._ripupCount > rhs._ripupCount + (int)Session::getRipupCost() ) return false;
|
//int rhsRipupCost = (rhs._dataState<<2) + rhs._ripupCount;
|
||||||
|
//if ( lhsRipupCost + (int)Session::getRipupCost() < rhsRipupCost ) return true;
|
||||||
if ( lhsRipupCost + (int)Session::getRipupCost() < rhsRipupCost ) return true;
|
//if ( lhsRipupCost > (int)Session::getRipupCost() + rhsRipupCost ) return false;
|
||||||
if ( lhsRipupCost > (int)Session::getRipupCost() + rhsRipupCost ) return false;
|
|
||||||
|
|
||||||
if ( lhs._overlap xor rhs._overlap ) return rhs._overlap;
|
if ( lhs._overlap xor rhs._overlap ) return rhs._overlap;
|
||||||
|
|
||||||
//std::cerr << "lhs:" << lhs._ripupCount
|
|
||||||
// << " rhs:" << rhs._ripupCount
|
|
||||||
// << " " << rhs._ripupCount - lhs._ripupCount << " > " << Session::getRipupCost()
|
|
||||||
// << std::endl;
|
|
||||||
//if ( lhs._ripupCount - rhs._ripupCount > (int)Session::getRipupCost() ) return false;
|
|
||||||
|
|
||||||
if ( lhs._terminals < rhs._terminals ) return true;
|
if ( lhs._terminals < rhs._terminals ) return true;
|
||||||
if ( lhs._terminals > rhs._terminals ) return false;
|
if ( lhs._terminals > rhs._terminals ) return false;
|
||||||
|
|
||||||
if ( lhs._delta < rhs._delta ) return true;
|
if ( lhs._delta < rhs._delta ) return true;
|
||||||
if ( lhs._delta > rhs._delta ) return false;
|
if ( lhs._delta > rhs._delta ) return false;
|
||||||
|
|
||||||
if ( lhs._axisWeight < rhs._axisWeight ) return true;
|
if ( not (_flags & TrackCost::IgnoreAxisWeight) ) {
|
||||||
if ( lhs._axisWeight > rhs._axisWeight ) return false;
|
if ( lhs._axisWeight < rhs._axisWeight ) return true;
|
||||||
|
if ( lhs._axisWeight > rhs._axisWeight ) return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( lhs._deltaPerpand < rhs._deltaPerpand ) return true;
|
if ( lhs._deltaPerpand < rhs._deltaPerpand ) return true;
|
||||||
if ( lhs._deltaPerpand > rhs._deltaPerpand ) return false;
|
if ( lhs._deltaPerpand > rhs._deltaPerpand ) return false;
|
||||||
|
@ -161,10 +174,13 @@ namespace Kite {
|
||||||
string s = "<" + _getTypeName();
|
string s = "<" + _getTypeName();
|
||||||
|
|
||||||
s += " " + getString(_track);
|
s += " " + getString(_track);
|
||||||
s += " " + getString(_ripupCount);
|
s += " " + getString(_dataState);
|
||||||
s += " " + string ( (_blockage )?"b":"-" );
|
s += "+" + getString(_ripupCount);
|
||||||
s += string ( (_hardOverlap)?"h":"-" );
|
s += ":" + getString((_dataState<<2)+_ripupCount);
|
||||||
s += string ( (_overlap )?"o":"-" );
|
s += " " + string ( (_blockage )?"b":"-" );
|
||||||
|
s += string ( (_hardOverlap )?"h":"-" );
|
||||||
|
s += string ( (_overlap )?"o":"-" );
|
||||||
|
s += string ( (_overlapGlobal)?"g":"-" );
|
||||||
s += " " + getString(_terminals);
|
s += " " + getString(_terminals);
|
||||||
s += "/" + DbU::getValueString(_delta);
|
s += "/" + DbU::getValueString(_delta);
|
||||||
s += "/" + DbU::getValueString(_axisWeight);
|
s += "/" + DbU::getValueString(_axisWeight);
|
||||||
|
|
|
@ -162,7 +162,7 @@ namespace Kite {
|
||||||
unsigned int TrackElement::getDogLegOrder () const { return 0; }
|
unsigned int TrackElement::getDogLegOrder () const { return 0; }
|
||||||
Interval TrackElement::getSourceConstraints () const { return Interval(); }
|
Interval TrackElement::getSourceConstraints () const { return Interval(); }
|
||||||
Interval TrackElement::getTargetConstraints () const { return Interval(); }
|
Interval TrackElement::getTargetConstraints () const { return Interval(); }
|
||||||
DataNegociate* TrackElement::getDataNegociate () const { return NULL; }
|
DataNegociate* TrackElement::getDataNegociate ( unsigned int ) const { return NULL; }
|
||||||
TrackElements TrackElement::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(NULL); }
|
TrackElements TrackElement::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(NULL); }
|
||||||
void TrackElement::setAllowOutsideGCell ( bool ) { }
|
void TrackElement::setAllowOutsideGCell ( bool ) { }
|
||||||
void TrackElement::setLock ( bool ) { }
|
void TrackElement::setLock ( bool ) { }
|
||||||
|
@ -177,12 +177,14 @@ namespace Kite {
|
||||||
|
|
||||||
bool TrackElement::canDesalignate () const { return false; }
|
bool TrackElement::canDesalignate () const { return false; }
|
||||||
bool TrackElement::canPivotUp ( float ) 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::canMoveUp ( float, unsigned int ) const { return false; };
|
||||||
bool TrackElement::canDogLeg () { return false; };
|
bool TrackElement::canDogLeg () { return false; };
|
||||||
bool TrackElement::canDogLeg ( Interval ) { return false; };
|
bool TrackElement::canDogLeg ( Interval ) { return false; };
|
||||||
bool TrackElement::canDogLegAt ( Katabatic::GCell*, bool allowReuse ) { return false; };
|
bool TrackElement::canDogLegAt ( Katabatic::GCell*, unsigned int ) { return false; };
|
||||||
TrackElement* TrackElement::getSourceDogLeg () { return NULL; }
|
TrackElement* TrackElement::getSourceDogLeg () { return NULL; }
|
||||||
TrackElement* TrackElement::getTargetDogLeg () { return NULL; }
|
TrackElement* TrackElement::getTargetDogLeg () { return NULL; }
|
||||||
|
TrackElement* TrackElement::getParent () const { return NULL; }
|
||||||
void TrackElement::dataInvalidate () { }
|
void TrackElement::dataInvalidate () { }
|
||||||
void TrackElement::eventInvalidate () { }
|
void TrackElement::eventInvalidate () { }
|
||||||
void TrackElement::setArea () { }
|
void TrackElement::setArea () { }
|
||||||
|
@ -197,6 +199,7 @@ namespace Kite {
|
||||||
void TrackElement::setAxis ( DbU::Unit, unsigned int flags ) { }
|
void TrackElement::setAxis ( DbU::Unit, unsigned int flags ) { }
|
||||||
void TrackElement::slacken () { }
|
void TrackElement::slacken () { }
|
||||||
bool TrackElement::moveUp ( unsigned int ) { return false; }
|
bool TrackElement::moveUp ( unsigned int ) { return false; }
|
||||||
|
bool TrackElement::moveDown ( unsigned int ) { return false; }
|
||||||
bool TrackElement::moveAside ( bool onLeft ) { return false; }
|
bool TrackElement::moveAside ( bool onLeft ) { return false; }
|
||||||
TrackElement* TrackElement::makeDogLeg () { return NULL; }
|
TrackElement* TrackElement::makeDogLeg () { return NULL; }
|
||||||
TrackElement* TrackElement::makeDogLeg ( Interval, bool& leftDogleg ) { return NULL; }
|
TrackElement* TrackElement::makeDogLeg ( Interval, bool& leftDogleg ) { return NULL; }
|
||||||
|
|
|
@ -111,14 +111,14 @@ namespace Kite {
|
||||||
guside = gcell->getUSide ( Constant::Horizontal /*, true*/ );
|
guside = gcell->getUSide ( Constant::Horizontal /*, true*/ );
|
||||||
Interval usedLength = guside.getIntersection ( segside );
|
Interval usedLength = guside.getIntersection ( segside );
|
||||||
|
|
||||||
gcell->addBlockage ( depth, (float)usedLength.getSize()/(float)guside.getSize() );
|
gcell->addBlockage ( depth, usedLength.getSize() );
|
||||||
gcell = right;
|
gcell = right;
|
||||||
}
|
}
|
||||||
if ( end ) {
|
if ( end ) {
|
||||||
guside = gcell->getUSide ( Constant::Horizontal /*, true*/ );
|
guside = gcell->getUSide ( Constant::Horizontal /*, true*/ );
|
||||||
Interval usedLength = guside.getIntersection ( segside );
|
Interval usedLength = guside.getIntersection ( segside );
|
||||||
|
|
||||||
end->addBlockage ( depth, (float)usedLength.getSize()/(float)guside.getSize() );
|
end->addBlockage ( depth, usedLength.getSize() );
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl;
|
cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl;
|
||||||
|
@ -141,14 +141,14 @@ namespace Kite {
|
||||||
guside = gcell->getUSide ( Constant::Vertical /*, true*/ );
|
guside = gcell->getUSide ( Constant::Vertical /*, true*/ );
|
||||||
Interval usedLength = guside.getIntersection ( segside );
|
Interval usedLength = guside.getIntersection ( segside );
|
||||||
|
|
||||||
gcell->addBlockage ( depth, (float)usedLength.getSize()/(float)guside.getSize() );
|
gcell->addBlockage ( depth, usedLength.getSize() );
|
||||||
gcell = up;
|
gcell = up;
|
||||||
}
|
}
|
||||||
if ( end ) {
|
if ( end ) {
|
||||||
guside = gcell->getUSide ( Constant::Vertical /*, true*/ );
|
guside = gcell->getUSide ( Constant::Vertical /*, true*/ );
|
||||||
Interval usedLength = guside.getIntersection ( segside );
|
Interval usedLength = guside.getIntersection ( segside );
|
||||||
|
|
||||||
end->addBlockage ( depth, (float)usedLength.getSize()/(float)guside.getSize() );
|
end->addBlockage ( depth, usedLength.getSize() );
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl;
|
cerr << Warning("TrackFixedSegment(): TrackFixedElement outside GCell grid.") << endl;
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "crlcore/RoutingGauge.h"
|
#include "crlcore/RoutingGauge.h"
|
||||||
#include "kite/DataNegociate.h"
|
#include "kite/DataNegociate.h"
|
||||||
#include "kite/TrackSegment.h"
|
#include "kite/TrackSegment.h"
|
||||||
#include "kite/TrackCost.h"
|
|
||||||
#include "kite/Track.h"
|
#include "kite/Track.h"
|
||||||
#include "kite/Session.h"
|
#include "kite/Session.h"
|
||||||
#include "kite/RoutingEvent.h"
|
#include "kite/RoutingEvent.h"
|
||||||
|
@ -157,7 +156,6 @@ namespace Kite {
|
||||||
unsigned int TrackSegment::getDogLegLevel () const { return _dogLegLevel; }
|
unsigned int TrackSegment::getDogLegLevel () const { return _dogLegLevel; }
|
||||||
Interval TrackSegment::getSourceConstraints () const { return _base->getSourceConstraints(); }
|
Interval TrackSegment::getSourceConstraints () const { return _base->getSourceConstraints(); }
|
||||||
Interval TrackSegment::getTargetConstraints () const { return _base->getTargetConstraints(); }
|
Interval TrackSegment::getTargetConstraints () const { return _base->getTargetConstraints(); }
|
||||||
DataNegociate* TrackSegment::getDataNegociate () const { return _data; }
|
|
||||||
TrackElements TrackSegment::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(this); }
|
TrackElements TrackSegment::getCollapsedPerpandiculars () { return new TrackElements_CollapsedPerpandicular(this); }
|
||||||
void TrackSegment::setAllowOutsideGCell ( bool state ) { _base->setAllowOutsideGCell(state,true); }
|
void TrackSegment::setAllowOutsideGCell ( bool state ) { _base->setAllowOutsideGCell(state,true); }
|
||||||
void TrackSegment::setLock ( bool state ) { _lock = state; }
|
void TrackSegment::setLock ( bool state ) { _lock = state; }
|
||||||
|
@ -196,12 +194,13 @@ namespace Kite {
|
||||||
{ return _base->getLayer(); }
|
{ return _base->getLayer(); }
|
||||||
|
|
||||||
|
|
||||||
// DbU::Unit TrackSegment::getSourceU () const
|
DataNegociate* TrackSegment::getDataNegociate ( unsigned int flags ) const
|
||||||
// { return _base->getSourceU(); }
|
{
|
||||||
|
if ( flags & TrackElement::DataSelf ) return _data;
|
||||||
|
|
||||||
|
TrackElement* parent = getParent();
|
||||||
// DbU::Unit TrackSegment::getTargetU () const
|
return (parent) ? parent->getDataNegociate() : NULL;
|
||||||
// { return _base->getTargetU(); }
|
}
|
||||||
|
|
||||||
|
|
||||||
TrackElement* TrackSegment::getNext () const
|
TrackElement* TrackSegment::getNext () const
|
||||||
|
@ -218,6 +217,16 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrackElement* TrackSegment::getParent () const
|
||||||
|
{
|
||||||
|
AutoSegment* baseParent = base()->getParent();
|
||||||
|
if ( not baseParent ) return NULL;
|
||||||
|
|
||||||
|
TrackElement* element = Session::lookup ( baseParent );
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Interval TrackSegment::getFreeInterval () const
|
Interval TrackSegment::getFreeInterval () const
|
||||||
{
|
{
|
||||||
if ( not _track ) return Interval(false);
|
if ( not _track ) return Interval(false);
|
||||||
|
@ -412,7 +421,7 @@ namespace Kite {
|
||||||
other->getTrack()->_check();
|
other->getTrack()->_check();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RoutingEvent* thisEvent = getDataNegociate()->getRoutingEvent();
|
RoutingEvent* thisEvent = getDataNegociate(TrackElement::DataSelf)->getRoutingEvent();
|
||||||
RoutingEvent* otherEvent = other->getDataNegociate()->getRoutingEvent();
|
RoutingEvent* otherEvent = other->getDataNegociate()->getRoutingEvent();
|
||||||
|
|
||||||
if ( thisEvent ) thisEvent ->setSegment ( other );
|
if ( thisEvent ) thisEvent ->setSegment ( other );
|
||||||
|
@ -459,6 +468,10 @@ namespace Kite {
|
||||||
{ return _base->canPivotUp(reserve); }
|
{ return _base->canPivotUp(reserve); }
|
||||||
|
|
||||||
|
|
||||||
|
bool TrackSegment::canPivotDown ( float reserve ) const
|
||||||
|
{ return _base->canPivotDown(reserve); }
|
||||||
|
|
||||||
|
|
||||||
bool TrackSegment::canMoveUp ( float reserve, unsigned int flags ) const
|
bool TrackSegment::canMoveUp ( float reserve, unsigned int flags ) const
|
||||||
{ return _base->canMoveUp ( reserve, flags ); }
|
{ return _base->canMoveUp ( reserve, flags ); }
|
||||||
|
|
||||||
|
@ -478,7 +491,7 @@ namespace Kite {
|
||||||
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
|
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
|
||||||
TrackElement* segment = Session::getNegociateWindow()->addTrackSegment(invalidateds[i],false);
|
TrackElement* segment = Session::getNegociateWindow()->addTrackSegment(invalidateds[i],false);
|
||||||
if ( segment != NULL ) {
|
if ( segment != NULL ) {
|
||||||
ltrace(200) << "moved: " << invalidateds[i] << endl;
|
ltrace(200) << "moved up: " << invalidateds[i] << endl;
|
||||||
segments.push_back ( segment );
|
segments.push_back ( segment );
|
||||||
// if ( (segment->getTrack() == NULL)
|
// if ( (segment->getTrack() == NULL)
|
||||||
// or (segment->getLayer() != segment->getTrack()->getLayer()) )
|
// or (segment->getLayer() != segment->getTrack()->getLayer()) )
|
||||||
|
@ -486,7 +499,45 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ( size_t i=0 ; i<segments.size() ; i++ ) {
|
for ( size_t i=0 ; i<segments.size() ; i++ ) {
|
||||||
ltrace(200) << "moved: " << segments[i] << endl;
|
ltrace(200) << "moved up: " << segments[i] << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if ( _data and success ) {
|
||||||
|
// _data->setState ( DataNegociate::ConflictSolve1, true );
|
||||||
|
// _data->resetRipupCount ();
|
||||||
|
// }
|
||||||
|
|
||||||
|
ltraceout(200);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TrackSegment::moveDown ( unsigned int flags )
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
ltrace(200) << "TrackSegment::moveDown() " << flags << endl;
|
||||||
|
ltracein(200);
|
||||||
|
|
||||||
|
success = base()->moveDown ( flags );
|
||||||
|
|
||||||
|
const vector<AutoSegment*>& invalidateds = Session::getInvalidateds();
|
||||||
|
if ( not invalidateds.empty() ) {
|
||||||
|
vector<TrackElement*> segments;
|
||||||
|
for ( size_t i=0 ; i<invalidateds.size() ; i++ ) {
|
||||||
|
TrackElement* segment = Session::getNegociateWindow()->addTrackSegment(invalidateds[i],false);
|
||||||
|
if ( segment != NULL ) {
|
||||||
|
ltrace(200) << "moved down: " << invalidateds[i] << endl;
|
||||||
|
segments.push_back ( segment );
|
||||||
|
// if ( (segment->getTrack() == NULL)
|
||||||
|
// or (segment->getLayer() != segment->getTrack()->getLayer()) )
|
||||||
|
segment->reschedule ( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( size_t i=0 ; i<segments.size() ; i++ ) {
|
||||||
|
ltrace(200) << "moved down: " << segments[i] << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,7 +701,7 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TrackSegment::canDogLegAt ( Katabatic::GCell* dogLegGCell, bool allowReuse )
|
bool TrackSegment::canDogLegAt ( Katabatic::GCell* dogLegGCell, unsigned int flags )
|
||||||
{
|
{
|
||||||
ltrace(200) << "TrackSegment::canDogLegAt(GCell*) " << dogLegGCell << endl;
|
ltrace(200) << "TrackSegment::canDogLegAt(GCell*) " << dogLegGCell << endl;
|
||||||
|
|
||||||
|
@ -683,7 +734,7 @@ namespace Kite {
|
||||||
isGCellInside = true;
|
isGCellInside = true;
|
||||||
if ( igcell == 0 ) {
|
if ( igcell == 0 ) {
|
||||||
if ( hasSourceDogLeg() ) {
|
if ( hasSourceDogLeg() ) {
|
||||||
if ( allowReuse ) return true;
|
if ( flags & TrackElement::AllowDoglegReuse ) return true;
|
||||||
|
|
||||||
ltrace(200) << "Cannot dogleg again in source GCell." << endl;
|
ltrace(200) << "Cannot dogleg again in source GCell." << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -691,7 +742,7 @@ namespace Kite {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( hasTargetDogLeg() && (igcell == gcells.size()-1) ) {
|
if ( hasTargetDogLeg() && (igcell == gcells.size()-1) ) {
|
||||||
if ( allowReuse ) return true;
|
if ( flags & TrackElement::AllowDoglegReuse ) return true;
|
||||||
|
|
||||||
ltrace(200) << "Cannot dogleg again in target GCell." << endl;
|
ltrace(200) << "Cannot dogleg again in target GCell." << endl;
|
||||||
return false;
|
return false;
|
||||||
|
@ -848,7 +899,7 @@ namespace Kite {
|
||||||
|
|
||||||
bool coherency = true;
|
bool coherency = true;
|
||||||
|
|
||||||
if ( !base()->isCanonical() ) {
|
if ( not base()->isCanonical() ) {
|
||||||
cerr << "[CHECK] " << this << " supporting AutoSegment is not canonical." << endl;
|
cerr << "[CHECK] " << this << " supporting AutoSegment is not canonical." << endl;
|
||||||
coherency = false;
|
coherency = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,9 @@ namespace Kite {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum SlackState { RipupPerpandiculars= 1
|
enum SlackState { RipupPerpandiculars= 1
|
||||||
, Minimize = 2
|
, Desalignate = 2
|
||||||
, DogLeg = 3
|
, Minimize = 3
|
||||||
, Desalignate = 4
|
, DogLeg = 4
|
||||||
, Slacken = 5
|
, Slacken = 5
|
||||||
, ConflictSolve1 = 6
|
, ConflictSolve1 = 6
|
||||||
, ConflictSolve2 = 7
|
, ConflictSolve2 = 7
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace Hurricane {
|
||||||
#include "katabatic/Grid.h"
|
#include "katabatic/Grid.h"
|
||||||
#include "kite/RoutingEventQueue.h"
|
#include "kite/RoutingEventQueue.h"
|
||||||
#include "kite/RoutingEventHistory.h"
|
#include "kite/RoutingEventHistory.h"
|
||||||
|
#include "kite/RoutingEventLoop.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Kite {
|
namespace Kite {
|
||||||
|
@ -114,6 +115,7 @@ namespace Kite {
|
||||||
inline const Katabatic::GCellVector& getGCells () const;
|
inline const Katabatic::GCellVector& getGCells () const;
|
||||||
inline RoutingEventQueue& getEventQueue ();
|
inline RoutingEventQueue& getEventQueue ();
|
||||||
inline RoutingEventHistory& getEventHistory ();
|
inline RoutingEventHistory& getEventHistory ();
|
||||||
|
inline RoutingEventLoop& getEventLoop ();
|
||||||
inline Stage getStage () const;
|
inline Stage getStage () const;
|
||||||
void setGCells ( const Katabatic::GCellVector& );
|
void setGCells ( const Katabatic::GCellVector& );
|
||||||
inline void setInterrupt ( bool );
|
inline void setInterrupt ( bool );
|
||||||
|
@ -139,6 +141,7 @@ namespace Kite {
|
||||||
std::vector<TrackElement*> _segments;
|
std::vector<TrackElement*> _segments;
|
||||||
RoutingEventQueue _eventQueue;
|
RoutingEventQueue _eventQueue;
|
||||||
RoutingEventHistory _eventHistory;
|
RoutingEventHistory _eventHistory;
|
||||||
|
RoutingEventLoop _eventLoop;
|
||||||
Statistics _statistics;
|
Statistics _statistics;
|
||||||
|
|
||||||
// Constructors.
|
// Constructors.
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#define __KITE_ROUTING_EVENT__
|
#define __KITE_ROUTING_EVENT__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "hurricane/Interval.h"
|
#include "hurricane/Interval.h"
|
||||||
namespace Hurricane {
|
namespace Hurricane {
|
||||||
|
@ -48,6 +49,7 @@ namespace Kite {
|
||||||
class Track;
|
class Track;
|
||||||
class RoutingEventHistory;
|
class RoutingEventHistory;
|
||||||
class RoutingEventQueue;
|
class RoutingEventQueue;
|
||||||
|
class RoutingEventLoop;
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -91,66 +93,72 @@ namespace Kite {
|
||||||
enum Mode { Negociate=1, Pack=2, PostPack=3 };
|
enum Mode { Negociate=1, Pack=2, PostPack=3 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static size_t getAllocateds ();
|
static size_t getAllocateds ();
|
||||||
static size_t getProcesseds ();
|
static size_t getProcesseds ();
|
||||||
static size_t getCloneds ();
|
static size_t getCloneds ();
|
||||||
static void resetProcesseds ();
|
static void resetProcesseds ();
|
||||||
public:
|
public:
|
||||||
static RoutingEvent* create ( TrackElement*, unsigned int mode=Negociate );
|
static RoutingEvent* create ( TrackElement*, unsigned int mode=Negociate );
|
||||||
RoutingEvent* clone () const;
|
RoutingEvent* clone () const;
|
||||||
void destroy ();
|
void destroy ();
|
||||||
inline bool isCloned () const;
|
inline bool isCloned () const;
|
||||||
inline bool isValid () const;
|
inline bool isValid () const;
|
||||||
bool isUnimplemented () const;
|
bool isUnimplemented () const;
|
||||||
inline bool isProcessed () const;
|
inline bool isProcessed () const;
|
||||||
inline bool isDisabled () const;
|
inline bool isDisabled () const;
|
||||||
inline bool isForcedToHint () const;
|
inline bool isForcedToHint () const;
|
||||||
inline bool isSheared () const;
|
inline bool isSheared () const;
|
||||||
inline bool getMode () const;
|
inline bool isRipedByLocal () const;
|
||||||
inline bool canMinimize () const;
|
inline bool getMode () const;
|
||||||
unsigned int getState () const;
|
inline bool canMinimize () const;
|
||||||
inline const Key& getKey () const;
|
unsigned int getState () const;
|
||||||
inline TrackElement* getSegment () const;
|
inline const Key& getKey () const;
|
||||||
inline const vector<TrackElement*>& getPerpandiculars () const;
|
inline TrackElement* getSegment () const;
|
||||||
inline DbU::Unit getAxisHint () const;
|
inline const vector<TrackElement*>& getPerpandiculars () const;
|
||||||
inline DbU::Unit getAxisHistory () const;
|
inline DbU::Unit getAxisHint () const;
|
||||||
long getAxisWeight ( DbU::Unit ) const;
|
inline DbU::Unit getAxisHistory () const;
|
||||||
inline const Interval& getOptimalAxis () const;
|
inline long getAxisWeight ( DbU::Unit ) const;
|
||||||
inline const Interval& getConstraints () const;
|
inline const Interval& getOptimalAxis () const;
|
||||||
inline const Interval& getOptimal () const;
|
inline const Interval& getConstraints () const;
|
||||||
inline const Interval& getPerpandicular () const;
|
inline const Interval& getOptimal () const;
|
||||||
inline Katabatic::GCell* getShearGCell () const;
|
inline const Interval& getPerpandicular () const;
|
||||||
inline float getPriority () const;
|
inline Katabatic::GCell* getShearGCell () const;
|
||||||
inline unsigned int getTracksNb () const;
|
inline float getPriority () const;
|
||||||
inline unsigned int getTracksFree () const;
|
inline unsigned int getTracksNb () const;
|
||||||
inline unsigned int getInsertState () const;
|
inline unsigned int getTracksFree () const;
|
||||||
inline unsigned int getEventLevel () const;
|
inline unsigned int getInsertState () const;
|
||||||
inline void invalidate ( bool withPerpandiculars=false, bool withConstraints=false );
|
inline unsigned int getEventLevel () const;
|
||||||
void revalidate ( bool force=false );
|
inline void invalidate ( bool withPerpandiculars=false, bool withConstraints=false );
|
||||||
inline void updateKey ();
|
void revalidate ( bool force=false );
|
||||||
void process ( RoutingEventQueue&, RoutingEventHistory& );
|
inline void updateKey ();
|
||||||
void setSegment ( TrackElement* );
|
void process ( RoutingEventQueue&
|
||||||
RoutingEvent* reschedule ( RoutingEventQueue&, unsigned int eventLevel );
|
, RoutingEventHistory&
|
||||||
inline void setMode ( unsigned int );
|
, RoutingEventLoop&
|
||||||
void setState ( unsigned int );
|
);
|
||||||
inline void setProcessed ( bool state=true );
|
void setSegment ( TrackElement* );
|
||||||
inline void setDisabled ( bool state=true );
|
RoutingEvent* reschedule ( RoutingEventQueue&, unsigned int eventLevel );
|
||||||
inline void setMinimized ( bool state=true );
|
inline void setMode ( unsigned int );
|
||||||
void setEventLevel ( unsigned int );
|
void setState ( unsigned int );
|
||||||
inline void setTracksFree ( unsigned int );
|
inline void setProcessed ( bool state=true );
|
||||||
inline void setForcedToHint ( bool state = true );
|
inline void setDisabled ( bool state=true );
|
||||||
void setAxisHint ( DbU::Unit );
|
inline void setMinimized ( bool state=true );
|
||||||
inline void setOptimalAxis ( Interval );
|
inline void setRipedByLocal ( bool state=true );
|
||||||
inline void incInsertState ();
|
void setEventLevel ( unsigned int );
|
||||||
inline void resetInsertState ();
|
inline void setTracksFree ( unsigned int );
|
||||||
void _processNegociate ( RoutingEventQueue&, RoutingEventHistory& );
|
inline void setForcedToHint ( bool state = true );
|
||||||
void _processPacking ( RoutingEventQueue&, RoutingEventHistory& );
|
void setAxisHint ( DbU::Unit );
|
||||||
Record* _getRecord () const;
|
void cacheAxisHint ();
|
||||||
string _getString () const;
|
inline void setOptimalAxis ( Interval );
|
||||||
string _getTypeName () const;
|
inline void incInsertState ();
|
||||||
|
inline void resetInsertState ();
|
||||||
|
void _processNegociate ( RoutingEventQueue&, RoutingEventHistory& );
|
||||||
|
void _processPacking ( RoutingEventQueue&, RoutingEventHistory& );
|
||||||
|
Record* _getRecord () const;
|
||||||
|
string _getString () const;
|
||||||
|
string _getTypeName () const;
|
||||||
private:
|
private:
|
||||||
RoutingEvent ( TrackElement*, unsigned int mode );
|
RoutingEvent ( TrackElement*, unsigned int mode );
|
||||||
~RoutingEvent ();
|
~RoutingEvent ();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Attributes.
|
// Attributes.
|
||||||
|
@ -166,6 +174,7 @@ namespace Kite {
|
||||||
bool _canHandleConstraints;
|
bool _canHandleConstraints;
|
||||||
bool _minimized;
|
bool _minimized;
|
||||||
bool _forceToHint;
|
bool _forceToHint;
|
||||||
|
bool _ripedByLocal;
|
||||||
TrackElement* _segment;
|
TrackElement* _segment;
|
||||||
DbU::Unit _axisHistory;
|
DbU::Unit _axisHistory;
|
||||||
DbU::Unit _axisHint;
|
DbU::Unit _axisHint;
|
||||||
|
@ -193,13 +202,15 @@ namespace Kite {
|
||||||
inline bool RoutingEvent::isDisabled () const { return _disabled; }
|
inline bool RoutingEvent::isDisabled () const { return _disabled; }
|
||||||
inline bool RoutingEvent::isForcedToHint () const { return _forceToHint; }
|
inline bool RoutingEvent::isForcedToHint () const { return _forceToHint; }
|
||||||
inline bool RoutingEvent::isSheared () const { return (_shearGCell != NULL); }
|
inline bool RoutingEvent::isSheared () const { return (_shearGCell != NULL); }
|
||||||
|
inline bool RoutingEvent::isRipedByLocal () const { return _ripedByLocal; }
|
||||||
inline bool RoutingEvent::getMode () const { return _mode; }
|
inline bool RoutingEvent::getMode () const { return _mode; }
|
||||||
inline bool RoutingEvent::canMinimize () const { return !_minimized; }
|
inline bool RoutingEvent::canMinimize () const { return !_minimized; }
|
||||||
inline const RoutingEvent::Key& RoutingEvent::getKey () const { return _key; }
|
inline const RoutingEvent::Key& RoutingEvent::getKey () const { return _key; }
|
||||||
inline TrackElement* RoutingEvent::getSegment () const { return _segment; }
|
inline TrackElement* RoutingEvent::getSegment () const { return _segment; }
|
||||||
inline const vector<TrackElement*>& RoutingEvent::getPerpandiculars () const { return _perpandiculars; }
|
inline const vector<TrackElement*>& RoutingEvent::getPerpandiculars () const { return _perpandiculars; }
|
||||||
inline DbU::Unit RoutingEvent::getAxisHint () const { return _axisHint; }
|
|
||||||
inline DbU::Unit RoutingEvent::getAxisHistory () const { return _axisHistory; }
|
inline DbU::Unit RoutingEvent::getAxisHistory () const { return _axisHistory; }
|
||||||
|
inline DbU::Unit RoutingEvent::getAxisHint () const { return _axisHint; }
|
||||||
|
inline long RoutingEvent::getAxisWeight ( DbU::Unit axis ) const { return abs(axis - getAxisHint()); }
|
||||||
inline const Interval& RoutingEvent::getOptimalAxis () const { return _optimalAxis; }
|
inline const Interval& RoutingEvent::getOptimalAxis () const { return _optimalAxis; }
|
||||||
inline const Interval& RoutingEvent::getConstraints () const { return _constraints; }
|
inline const Interval& RoutingEvent::getConstraints () const { return _constraints; }
|
||||||
inline const Interval& RoutingEvent::getOptimal () const { return _optimal; }
|
inline const Interval& RoutingEvent::getOptimal () const { return _optimal; }
|
||||||
|
@ -214,6 +225,7 @@ namespace Kite {
|
||||||
inline void RoutingEvent::setProcessed ( bool state ) { _processed = state; }
|
inline void RoutingEvent::setProcessed ( bool state ) { _processed = state; }
|
||||||
inline void RoutingEvent::setDisabled ( bool state ) { _disabled = state; }
|
inline void RoutingEvent::setDisabled ( bool state ) { _disabled = state; }
|
||||||
inline void RoutingEvent::setMinimized ( bool state ) { _minimized = state; }
|
inline void RoutingEvent::setMinimized ( bool state ) { _minimized = state; }
|
||||||
|
inline void RoutingEvent::setRipedByLocal ( bool state ) { _ripedByLocal = state; }
|
||||||
inline void RoutingEvent::setTracksFree ( unsigned int nb ) { _tracksFree = nb; }
|
inline void RoutingEvent::setTracksFree ( unsigned int nb ) { _tracksFree = nb; }
|
||||||
inline void RoutingEvent::setForcedToHint ( bool state ) { _forceToHint = state; }
|
inline void RoutingEvent::setForcedToHint ( bool state ) { _forceToHint = state; }
|
||||||
inline void RoutingEvent::setOptimalAxis ( Interval i ) { _optimalAxis = i; }
|
inline void RoutingEvent::setOptimalAxis ( Interval i ) { _optimalAxis = i; }
|
||||||
|
|
|
@ -49,7 +49,6 @@ namespace Kite {
|
||||||
public:
|
public:
|
||||||
RoutingEventHistory ();
|
RoutingEventHistory ();
|
||||||
~RoutingEventHistory ();
|
~RoutingEventHistory ();
|
||||||
inline bool looping () const;
|
|
||||||
inline bool empty () const;
|
inline bool empty () const;
|
||||||
inline size_t size () const;
|
inline size_t size () const;
|
||||||
RoutingEvent* getNth ( size_t ) const;
|
RoutingEvent* getNth ( size_t ) const;
|
||||||
|
@ -64,7 +63,6 @@ namespace Kite {
|
||||||
protected:
|
protected:
|
||||||
// Attributes.
|
// Attributes.
|
||||||
vector<RoutingEvent*> _events;
|
vector<RoutingEvent*> _events;
|
||||||
size_t _identicals;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RoutingEventHistory& operator= ( const RoutingEventHistory& );
|
RoutingEventHistory& operator= ( const RoutingEventHistory& );
|
||||||
|
@ -74,7 +72,6 @@ namespace Kite {
|
||||||
|
|
||||||
|
|
||||||
// Inline Functions.
|
// Inline Functions.
|
||||||
inline bool RoutingEventHistory::looping () const { return _identicals > 30; }
|
|
||||||
inline bool RoutingEventHistory::empty () const { return _events.empty(); }
|
inline bool RoutingEventHistory::empty () const { return _events.empty(); }
|
||||||
inline size_t RoutingEventHistory::size () const { return _events.size(); }
|
inline size_t RoutingEventHistory::size () const { return _events.size(); }
|
||||||
inline string RoutingEventHistory::_getTypeName () const { return "RoutingEventHistory"; }
|
inline string RoutingEventHistory::_getTypeName () const { return "RoutingEventHistory"; }
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) UPMC/LIP6 2008-2010, All Rights Reserved
|
||||||
|
//
|
||||||
|
// ===================================================================
|
||||||
|
//
|
||||||
|
// $Id$
|
||||||
|
//
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
// | |
|
||||||
|
// | 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++ Header : "./kite/RoutingEventLoop.h" |
|
||||||
|
// | *************************************************************** |
|
||||||
|
// | U p d a t e s |
|
||||||
|
// | |
|
||||||
|
// x-----------------------------------------------------------------x
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __KITE_ROUTING_EVENT_LOOP__
|
||||||
|
#define __KITE_ROUTING_EVENT_LOOP__
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Kite {
|
||||||
|
|
||||||
|
class RoutingEvent;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "RoutingEventLoop".
|
||||||
|
|
||||||
|
|
||||||
|
class RoutingEventLoop {
|
||||||
|
public:
|
||||||
|
class Element {
|
||||||
|
public:
|
||||||
|
inline Element ( size_t id=0, size_t timestamp=0 );
|
||||||
|
public:
|
||||||
|
size_t _id;
|
||||||
|
size_t _timestamp;
|
||||||
|
int _count;
|
||||||
|
};
|
||||||
|
class CompareByTimestamp {
|
||||||
|
public:
|
||||||
|
inline bool operator() ( const Element& lhs, const Element& rhs );
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
RoutingEventLoop ( size_t depth=10, int limit=20 );
|
||||||
|
inline bool isLooping () const;
|
||||||
|
inline int getMaxCount () const;
|
||||||
|
inline const std::vector<Element>& getElements () const;
|
||||||
|
void update ( size_t id );
|
||||||
|
void erase ( size_t id );
|
||||||
|
private:
|
||||||
|
std::vector<Element> _elements;
|
||||||
|
size_t _depth;
|
||||||
|
int _maxCount;
|
||||||
|
int _countLimit;
|
||||||
|
bool _isLooping;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline RoutingEventLoop::Element::Element ( size_t id, size_t timestamp )
|
||||||
|
: _id(id), _timestamp(timestamp), _count(1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool RoutingEventLoop::CompareByTimestamp::operator() ( const RoutingEventLoop::Element& lhs, const RoutingEventLoop::Element& rhs )
|
||||||
|
{ return lhs._timestamp > rhs._timestamp; }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool RoutingEventLoop::isLooping () const { return _isLooping; }
|
||||||
|
inline int RoutingEventLoop::getMaxCount () const { return _maxCount; }
|
||||||
|
inline const std::vector<RoutingEventLoop::Element>&
|
||||||
|
RoutingEventLoop::getElements () const { return _elements; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Kite namespace.
|
||||||
|
|
||||||
|
|
||||||
|
//INSPECTOR_P_SUPPORT(Kite::RoutingEvent);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __KITE_ROUTING_EVENT_LOOP__
|
|
@ -30,6 +30,9 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "hurricane/Interval.h"
|
#include "hurricane/Interval.h"
|
||||||
|
namespace Hurricane {
|
||||||
|
class Net;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Kite {
|
namespace Kite {
|
||||||
|
@ -39,6 +42,7 @@ namespace Kite {
|
||||||
using Hurricane::Record;
|
using Hurricane::Record;
|
||||||
using Hurricane::DbU;
|
using Hurricane::DbU;
|
||||||
using Hurricane::Interval;
|
using Hurricane::Interval;
|
||||||
|
using Hurricane::Net;
|
||||||
class Track;
|
class Track;
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +50,8 @@ namespace Kite {
|
||||||
// Class : "TrackCost".
|
// Class : "TrackCost".
|
||||||
|
|
||||||
class TrackCost {
|
class TrackCost {
|
||||||
|
public:
|
||||||
|
enum Flags { IgnoreAxisWeight=0x1, DiscardGlobals=0x2 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Sub-Class: "CompareByDelta()".
|
// Sub-Class: "CompareByDelta()".
|
||||||
|
@ -53,52 +59,61 @@ namespace Kite {
|
||||||
public:
|
public:
|
||||||
bool operator() ( const TrackCost& lhs, const TrackCost& rhs );
|
bool operator() ( const TrackCost& lhs, const TrackCost& rhs );
|
||||||
};
|
};
|
||||||
|
class Compare {
|
||||||
|
public:
|
||||||
|
inline Compare ( unsigned int flags=0 );
|
||||||
|
bool operator() ( const TrackCost& lhs, const TrackCost& rhs );
|
||||||
|
private:
|
||||||
|
unsigned int _flags;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TrackCost ( Track* track
|
TrackCost ( Track* track
|
||||||
, const Interval& interval
|
, const Interval& interval
|
||||||
, size_t begin
|
, size_t begin
|
||||||
, size_t end
|
, size_t end
|
||||||
);
|
, Net* net
|
||||||
~TrackCost ();
|
);
|
||||||
inline bool isBlockage () const;
|
~TrackCost ();
|
||||||
inline bool isFixed () const;
|
inline bool isBlockage () const;
|
||||||
inline bool isInfinite () const;
|
inline bool isFixed () const;
|
||||||
inline bool isOverlap () const;
|
inline bool isInfinite () const;
|
||||||
inline bool isLeftOverlap () const;
|
inline bool isOverlap () const;
|
||||||
inline bool isRightOverlap () const;
|
inline bool isLeftOverlap () const;
|
||||||
inline bool isHardOverlap () const;
|
inline bool isRightOverlap () const;
|
||||||
bool isFree () const;
|
inline bool isHardOverlap () const;
|
||||||
inline Track* getTrack () const;
|
inline bool isOverlapGlobal () const;
|
||||||
inline size_t getBegin () const;
|
bool isFree () const;
|
||||||
inline size_t getEnd () const;
|
inline Track* getTrack () const;
|
||||||
inline const Interval& getInterval () const;
|
inline size_t getBegin () const;
|
||||||
inline unsigned int getTerminals () const;
|
inline size_t getEnd () const;
|
||||||
inline DbU::Unit getDelta () const;
|
inline const Interval& getInterval () const;
|
||||||
inline DbU::Unit getDeltaPerpand () const;
|
inline unsigned int getTerminals () const;
|
||||||
inline long getAxisWeight () const;
|
inline DbU::Unit getDelta () const;
|
||||||
inline int getRipupCount () const;
|
inline DbU::Unit getDeltaPerpand () const;
|
||||||
inline unsigned int getDataState () const;
|
inline long getAxisWeight () const;
|
||||||
inline void setBlockage ();
|
inline int getRipupCount () const;
|
||||||
inline void setFixed ();
|
inline unsigned int getDataState () const;
|
||||||
inline void setInfinite ();
|
inline void setBlockage ();
|
||||||
inline void setOverlap ();
|
inline void setFixed ();
|
||||||
inline void setLeftOverlap ();
|
inline void setInfinite ();
|
||||||
inline void setRightOverlap ();
|
inline void setOverlap ();
|
||||||
inline void setHardOverlap ();
|
inline void setLeftOverlap ();
|
||||||
inline void incTerminals ( unsigned int );
|
inline void setRightOverlap ();
|
||||||
inline void incDelta ( DbU::Unit );
|
inline void setHardOverlap ();
|
||||||
inline void incDeltaPerpand ( DbU::Unit );
|
inline void setOverlapGlobal ();
|
||||||
inline void incDeltaShared ( DbU::Unit );
|
inline void incTerminals ( unsigned int );
|
||||||
inline void setAxisWeight ( DbU::Unit );
|
inline void incDelta ( DbU::Unit );
|
||||||
inline void mergeRipupCount ( int );
|
inline void incDeltaPerpand ( DbU::Unit );
|
||||||
inline void mergeDataState ( unsigned int );
|
inline void incDeltaShared ( DbU::Unit );
|
||||||
void consolidate ();
|
inline void setAxisWeight ( DbU::Unit );
|
||||||
Record* _getRecord () const;
|
inline void mergeRipupCount ( int );
|
||||||
string _getString () const;
|
inline void mergeDataState ( unsigned int );
|
||||||
inline string _getTypeName () const;
|
void consolidate ();
|
||||||
|
Record* _getRecord () const;
|
||||||
|
string _getString () const;
|
||||||
|
inline string _getTypeName () const;
|
||||||
// Operators.
|
// Operators.
|
||||||
friend bool operator< ( const TrackCost& lhs, const TrackCost& rhs );
|
|
||||||
|
|
||||||
// Attributes.
|
// Attributes.
|
||||||
protected:
|
protected:
|
||||||
|
@ -113,6 +128,7 @@ namespace Kite {
|
||||||
bool _overlap;
|
bool _overlap;
|
||||||
bool _leftOverlap;
|
bool _leftOverlap;
|
||||||
bool _rightOverlap;
|
bool _rightOverlap;
|
||||||
|
bool _overlapGlobal;
|
||||||
unsigned int _terminals;
|
unsigned int _terminals;
|
||||||
DbU::Unit _delta;
|
DbU::Unit _delta;
|
||||||
DbU::Unit _deltaShared;
|
DbU::Unit _deltaShared;
|
||||||
|
@ -133,6 +149,7 @@ namespace Kite {
|
||||||
inline bool TrackCost::isLeftOverlap () const { return _leftOverlap; }
|
inline bool TrackCost::isLeftOverlap () const { return _leftOverlap; }
|
||||||
inline bool TrackCost::isRightOverlap () const { return _rightOverlap; }
|
inline bool TrackCost::isRightOverlap () const { return _rightOverlap; }
|
||||||
inline bool TrackCost::isHardOverlap () const { return _hardOverlap; }
|
inline bool TrackCost::isHardOverlap () const { return _hardOverlap; }
|
||||||
|
inline bool TrackCost::isOverlapGlobal () const { return _overlapGlobal; }
|
||||||
inline Track* TrackCost::getTrack () const { return _track; }
|
inline Track* TrackCost::getTrack () const { return _track; }
|
||||||
inline size_t TrackCost::getBegin () const { return _begin; }
|
inline size_t TrackCost::getBegin () const { return _begin; }
|
||||||
inline size_t TrackCost::getEnd () const { return _end; }
|
inline size_t TrackCost::getEnd () const { return _end; }
|
||||||
|
@ -149,6 +166,7 @@ namespace Kite {
|
||||||
inline void TrackCost::setLeftOverlap () { _leftOverlap = true; }
|
inline void TrackCost::setLeftOverlap () { _leftOverlap = true; }
|
||||||
inline void TrackCost::setRightOverlap () { _rightOverlap = true; }
|
inline void TrackCost::setRightOverlap () { _rightOverlap = true; }
|
||||||
inline void TrackCost::setHardOverlap () { _hardOverlap = true; }
|
inline void TrackCost::setHardOverlap () { _hardOverlap = true; }
|
||||||
|
inline void TrackCost::setOverlapGlobal() { _overlapGlobal = true; }
|
||||||
inline void TrackCost::incTerminals ( unsigned int terminals ) { _terminals += terminals; }
|
inline void TrackCost::incTerminals ( unsigned int terminals ) { _terminals += terminals; }
|
||||||
inline void TrackCost::incDelta ( DbU::Unit delta ) { _delta += delta; }
|
inline void TrackCost::incDelta ( DbU::Unit delta ) { _delta += delta; }
|
||||||
inline void TrackCost::incDeltaPerpand ( DbU::Unit delta ) { _deltaPerpand += delta; }
|
inline void TrackCost::incDeltaPerpand ( DbU::Unit delta ) { _deltaPerpand += delta; }
|
||||||
|
@ -158,6 +176,8 @@ namespace Kite {
|
||||||
inline void TrackCost::mergeDataState ( unsigned int state ) { _dataState = (state>_dataState)?state:_dataState; }
|
inline void TrackCost::mergeDataState ( unsigned int state ) { _dataState = (state>_dataState)?state:_dataState; }
|
||||||
inline string TrackCost::_getTypeName () const { return "TrackCost"; }
|
inline string TrackCost::_getTypeName () const { return "TrackCost"; }
|
||||||
|
|
||||||
|
inline TrackCost::Compare::Compare ( unsigned int flags ) : _flags(flags) { }
|
||||||
|
|
||||||
|
|
||||||
} // End of Kite namespace.
|
} // End of Kite namespace.
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,14 @@ namespace Kite {
|
||||||
class TrackElement {
|
class TrackElement {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Flags { AddToGCells=0x1, RemoveFromGCells=0x2, UnRouted=0x4, Routed=0x8 };
|
enum Flags { AddToGCells =0x01
|
||||||
|
, RemoveFromGCells=0x02
|
||||||
|
, UnRouted =0x04
|
||||||
|
, Routed =0x08
|
||||||
|
, AllowDoglegReuse=0x10
|
||||||
|
, DataSelf =0x01
|
||||||
|
, DataParent =0x02
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Sub-Class: "Compare()".
|
// Sub-Class: "Compare()".
|
||||||
|
@ -116,13 +123,14 @@ namespace Kite {
|
||||||
virtual bool canGoOutsideGCell () const;
|
virtual bool canGoOutsideGCell () const;
|
||||||
virtual bool canSlacken () const;
|
virtual bool canSlacken () const;
|
||||||
virtual bool canPivotUp ( float reserve ) const;
|
virtual bool canPivotUp ( float reserve ) const;
|
||||||
virtual bool canMoveUp ( float reserve, unsigned int flags=/*Katabatic::AutoSegment::Propagate*/0 ) const;
|
virtual bool canPivotDown ( float reserve ) const;
|
||||||
|
virtual bool canMoveUp ( float reserve, unsigned int flags=AutoSegment::Propagate ) const;
|
||||||
virtual bool canRipple () const;
|
virtual bool canRipple () const;
|
||||||
virtual bool hasSourceDogLeg () const;
|
virtual bool hasSourceDogLeg () const;
|
||||||
virtual bool hasTargetDogLeg () const;
|
virtual bool hasTargetDogLeg () const;
|
||||||
virtual bool canDogLeg ();
|
virtual bool canDogLeg ();
|
||||||
virtual bool canDogLeg ( Interval );
|
virtual bool canDogLeg ( Interval );
|
||||||
virtual bool canDogLegAt ( Katabatic::GCell*, bool allowReuse=false );
|
virtual bool canDogLegAt ( Katabatic::GCell*, unsigned int flags=0 );
|
||||||
virtual unsigned long getId () const;
|
virtual unsigned long getId () const;
|
||||||
virtual unsigned int getDirection () const = 0;
|
virtual unsigned int getDirection () const = 0;
|
||||||
virtual Net* getNet () const = 0;
|
virtual Net* getNet () const = 0;
|
||||||
|
@ -135,6 +143,7 @@ namespace Kite {
|
||||||
virtual unsigned int getDogLegOrder () const;
|
virtual unsigned int getDogLegOrder () const;
|
||||||
virtual TrackElement* getNext () const;
|
virtual TrackElement* getNext () const;
|
||||||
virtual TrackElement* getPrevious () const;
|
virtual TrackElement* getPrevious () const;
|
||||||
|
virtual TrackElement* getParent () const;
|
||||||
virtual DbU::Unit getAxis () const = 0;
|
virtual DbU::Unit getAxis () const = 0;
|
||||||
inline DbU::Unit getSourceU () const;
|
inline DbU::Unit getSourceU () const;
|
||||||
inline DbU::Unit getTargetU () const;
|
inline DbU::Unit getTargetU () const;
|
||||||
|
@ -143,7 +152,7 @@ namespace Kite {
|
||||||
inline Interval getCanonicalInterval () const;
|
inline Interval getCanonicalInterval () const;
|
||||||
virtual Interval getSourceConstraints () const;
|
virtual Interval getSourceConstraints () const;
|
||||||
virtual Interval getTargetConstraints () const;
|
virtual Interval getTargetConstraints () const;
|
||||||
virtual DataNegociate* getDataNegociate () const;
|
virtual DataNegociate* getDataNegociate ( unsigned int flags=DataSelf ) const;
|
||||||
virtual TrackElement* getCanonical ( Interval& );
|
virtual TrackElement* getCanonical ( Interval& );
|
||||||
virtual size_t getGCells ( Katabatic::GCellVector& ) const;
|
virtual size_t getGCells ( Katabatic::GCellVector& ) const;
|
||||||
virtual TrackElement* getSourceDogLeg ();
|
virtual TrackElement* getSourceDogLeg ();
|
||||||
|
@ -174,7 +183,8 @@ namespace Kite {
|
||||||
virtual void invalidate ();
|
virtual void invalidate ();
|
||||||
virtual void setAxis ( DbU::Unit, unsigned int flags=Katabatic::AxisSet );
|
virtual void setAxis ( DbU::Unit, unsigned int flags=Katabatic::AxisSet );
|
||||||
virtual void slacken ();
|
virtual void slacken ();
|
||||||
virtual bool moveUp ( unsigned int flags=/*Katabatic::AutoSegment::Propagate*/0 );
|
virtual bool moveUp ( unsigned int flags=AutoSegment::Propagate );
|
||||||
|
virtual bool moveDown ( unsigned int flags=AutoSegment::Propagate );
|
||||||
virtual bool moveAside ( bool onLeft );
|
virtual bool moveAside ( bool onLeft );
|
||||||
virtual TrackElement* makeDogLeg ();
|
virtual TrackElement* makeDogLeg ();
|
||||||
virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg );
|
virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg );
|
||||||
|
|
|
@ -78,13 +78,14 @@ namespace Kite {
|
||||||
virtual bool canGoOutsideGCell () const;
|
virtual bool canGoOutsideGCell () const;
|
||||||
virtual bool canSlacken () const;
|
virtual bool canSlacken () const;
|
||||||
virtual bool canPivotUp ( float reserve ) const;
|
virtual bool canPivotUp ( float reserve ) const;
|
||||||
virtual bool canMoveUp ( float reserve, unsigned int flags=Katabatic::AutoSegment::Propagate ) const;
|
virtual bool canPivotDown ( float reserve ) const;
|
||||||
|
virtual bool canMoveUp ( float reserve, unsigned int flags ) const;
|
||||||
virtual bool canRipple () const;
|
virtual bool canRipple () const;
|
||||||
virtual bool hasSourceDogLeg () const;
|
virtual bool hasSourceDogLeg () const;
|
||||||
virtual bool hasTargetDogLeg () const;
|
virtual bool hasTargetDogLeg () const;
|
||||||
virtual bool canDogLeg ();
|
virtual bool canDogLeg ();
|
||||||
virtual bool canDogLeg ( Interval );
|
virtual bool canDogLeg ( Interval );
|
||||||
virtual bool canDogLegAt ( Katabatic::GCell*, bool allowReuse=false );
|
virtual bool canDogLegAt ( Katabatic::GCell*, unsigned int flags );
|
||||||
virtual unsigned long getId () const;
|
virtual unsigned long getId () const;
|
||||||
virtual unsigned int getDirection () const;
|
virtual unsigned int getDirection () const;
|
||||||
virtual Net* getNet () const;
|
virtual Net* getNet () const;
|
||||||
|
@ -93,11 +94,12 @@ namespace Kite {
|
||||||
virtual unsigned int getDogLegLevel () const;
|
virtual unsigned int getDogLegLevel () const;
|
||||||
virtual TrackElement* getNext () const;
|
virtual TrackElement* getNext () const;
|
||||||
virtual TrackElement* getPrevious () const;
|
virtual TrackElement* getPrevious () const;
|
||||||
|
virtual TrackElement* getParent () const;
|
||||||
virtual DbU::Unit getAxis () const;
|
virtual DbU::Unit getAxis () const;
|
||||||
virtual Interval getFreeInterval () const;
|
virtual Interval getFreeInterval () const;
|
||||||
virtual Interval getSourceConstraints () const;
|
virtual Interval getSourceConstraints () const;
|
||||||
virtual Interval getTargetConstraints () const;
|
virtual Interval getTargetConstraints () const;
|
||||||
virtual DataNegociate* getDataNegociate () const;
|
virtual DataNegociate* getDataNegociate ( unsigned int flags ) const;
|
||||||
virtual TrackElement* getCanonical ( Interval& );
|
virtual TrackElement* getCanonical ( Interval& );
|
||||||
virtual size_t getGCells ( vector<Katabatic::GCell*>& ) const;
|
virtual size_t getGCells ( vector<Katabatic::GCell*>& ) const;
|
||||||
virtual TrackElement* getSourceDogLeg ();
|
virtual TrackElement* getSourceDogLeg ();
|
||||||
|
@ -109,8 +111,8 @@ namespace Kite {
|
||||||
virtual void setAllowOutsideGCell ( bool );
|
virtual void setAllowOutsideGCell ( bool );
|
||||||
virtual void setRevalidated ( bool );
|
virtual void setRevalidated ( bool );
|
||||||
virtual void setCanRipple ( bool );
|
virtual void setCanRipple ( bool );
|
||||||
virtual void setSourceDogLeg ( bool state=true );
|
virtual void setSourceDogLeg ( bool );
|
||||||
virtual void setTargetDogLeg ( bool state=true );
|
virtual void setTargetDogLeg ( bool );
|
||||||
virtual void setLock ( bool );
|
virtual void setLock ( bool );
|
||||||
virtual void setRouted ( bool );
|
virtual void setRouted ( bool );
|
||||||
virtual void setTrack ( Track* );
|
virtual void setTrack ( Track* );
|
||||||
|
@ -119,11 +121,12 @@ namespace Kite {
|
||||||
virtual void swapTrack ( TrackElement* );
|
virtual void swapTrack ( TrackElement* );
|
||||||
virtual void reschedule ( unsigned int level );
|
virtual void reschedule ( unsigned int level );
|
||||||
virtual void detach ();
|
virtual void detach ();
|
||||||
virtual void revalidate ( bool invalidEvent=false );
|
virtual void revalidate ( bool invalidEvent );
|
||||||
virtual void invalidate ();
|
virtual void invalidate ();
|
||||||
virtual void setAxis ( DbU::Unit, unsigned int flags=Katabatic::AxisSet );
|
virtual void setAxis ( DbU::Unit, unsigned int flags );
|
||||||
virtual void slacken ();
|
virtual void slacken ();
|
||||||
virtual bool moveUp ( unsigned int flags=Katabatic::AutoSegment::Propagate );
|
virtual bool moveUp ( unsigned int flags );
|
||||||
|
virtual bool moveDown ( unsigned int flags );
|
||||||
virtual bool moveAside ( bool onLeft );
|
virtual bool moveAside ( bool onLeft );
|
||||||
virtual TrackElement* makeDogLeg ();
|
virtual TrackElement* makeDogLeg ();
|
||||||
virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg );
|
virtual TrackElement* makeDogLeg ( Interval, bool& leftDogleg );
|
||||||
|
|
Loading…
Reference in New Issue